LINUX.ORG.RU
ФорумTalks

Программистские перлы


0

0

Мой приятель, программируя, выдает иногда такие перлы:

1. Получая квадратный корень из числа, он однажды написал

y = x/sqrt(x);

2. Как-то, мы долго разбирались, что же должна по стандарту выдать конструкция:

i=0;

i= i++;

i=?

А что думаете вы?

:)

Re: Программистские перлы

> i=? > А что думаете вы?

пых подумал и сказал 0 :)

Cris ()

Re: Программистские перлы

> i=0; i= i++; i=? А что думаете вы?

о пневматическом музыкальном инструменте

dilmah ★★★★★ ()

Re: Программистские перлы

идиница, но вероятно от языка зависит

cvb ()

Re: Программистские перлы

> А что думаете вы?

0 или 1

Legioner ★★★★★ ()

Re: Программистские перлы

от компилятора зависит. а вообще яйца за такой код нужно отрезать тупым скальпелем. недизинфицированным.

asgard ()

Re: Программистские перлы

О, вижу, в треде есть "теоретики" и "практики" :)

Ну, сразу и яйца. Человек думал над алгоритмом, вот на автомате такое и написал. На самом деле, ему было нужно либо i=i+1; либо i++ :)

annoynimous ★★★★★ ()
Ответ на: Re: Программистские перлы от dilmah

Re: Программистские перлы

> о пневматическом музыкальном инструменте

не надо вот только "боян" кричать, ладно? Случай абсолютно реальный и более мной нигде не описанный. Если кто-то еще в Интернете написал что-то подобное, то к моему сообщению он никакого отношения не имеет

annoynimous ★★★★★ ()

Re: Программистские перлы

gcc выдал 1 :)

anonymous ()

Re: Программистские перлы

i=1, как и ожидалось, gcc version 4.0.3

record ★★★★★ ()
Ответ на: Re: Программистские перлы от annoynimous

Re: Программистские перлы

>если i=0 и j=0, то код

>j=i++;

>даст j=0 и i=1

По сути будет в первом случае так: i=i+1, с j вот так j=i+1. Вначале вычисляется значение, потом записывается в переменную стоящую в левой части равенства. Результат операции n++ не записывается в инкриментируемую переменную, т.к. форма постфиксная.

Всё верно.

anonymous ()
Ответ на: Re: Программистские перлы от annoynimous

Re: Программистские перлы

Угу, только интересен такой ещё момент:

(i += ++i)++; - gcc выдаст 3. Т.е. такими идиотскими конструкциями, за которые убивать таки надо, можно вычислять константы 1,2,3... Не факт, что с другим компилятором такой бред сойдет с рук.

(i += (i += ++i)++)++ == 6

- можно и другие константы целочесленные считать... Бред какой :)

Spectr ★★★ ()

Re: Программистские перлы

>i= i++;

неопределенный результат. зависит от реализации

anonymous ()
Ответ на: Re: Программистские перлы от anonymous

Re: Программистские перлы

>>(i += ++i)++;

>Синтаксически верно, вроде действительно 3 будет. Это что тайнопись?

Такие конструкции обычно появляются, когда программисты начинают спорить кто меньшим кол-вом различных знаков реализует простенький алгоритм (например, диофантово решето, или сортировку). Цифры само собой не используют. Обычно обходятся <10 знаков. :) Но код ВСТАВЛЯЕТ!

soomrack ★★★ ()
Ответ на: Re: Программистские перлы от anonymous

Re: Программистские перлы

>i= i++;

>неопределенный результат. зависит от реализации

Тогда хочу видеть реализацию, где результат будет не 1, если найдёшь

anonymous ()
Ответ на: Re: Программистские перлы от anonymous

Re: Программистские перлы

>>i=i++;
>>неопределенный результат. зависит от реализации

>Тогда хочу видеть реализацию, где результат будет не 1, если найдёшь

#include <iostream>
int main(){
int i=0;
i=i++;
std::cout<<i;
}

Первое что попалось под руку - gcc version 3.4.2 (mingw-special) - выдало 0. Здесь "неопределенный результат" не только единственно верный но и единственно разумный ответ. Не удивлюсь, что на результат сможет повлиять не только компилятор и его версия, но опции оптимизации. Это НЕ тот случай, когда теоретическая неопределённость компенсируется практической гарантированностью.

GPFault ★★ ()
Ответ на: Re: Программистские перлы от GPFault

Re: Программистские перлы

Я бы сказал, что теоретическая гарантированность не всегда подкрепляется компилятором.... а от GCC не ожидал... :)

anonymous ()

Re: Программистские перлы

ИМХО.. теоретически и практически i должна равняться 1... к нулю прибавить 1 получиться единица..)) Может я в чем-то ошибаюсь??

hard_sintex ()
Ответ на: Re: Программистские перлы от anonymous

Re: Программистские перлы

>Тогда хочу видеть реализацию, где результат будет не 1, если найдёшь

rip@riphome ~ $ echo 'int main() {int i=0;i=i++;return i;}' >test_inc.c && gcc test_inc.c -o test_inc && ./test_inc ; echo $?
0

>(i += ++i)++; - gcc выдаст 3. Т.е. такими идиотскими конструкциями, за которые убивать таки надо, можно вычислять константы 1,2,3... Не факт, что с другим компилятором такой бред сойдет с рук.

rip@riphome ~ $ echo 'int main() {int i=0;(i+=i++)++;return i;}' >test_inc.c && gcc test_inc.c -o test_inc && ./test_inc ; echo $?
test_inc.c: In function `main':
test_inc.c:1: error: invalid lvalue in increment
1
rip@riphome ~ $ echo 'int main() {int i=0;(i+=i++)++;return i;}' >test_inc.c && g++ test_inc.c -o test_inc && ./test_inc ; echo $?
2


rip@riphome ~ $ gcc --version
gcc (GCC) 3.4.6 (Gentoo 3.4.6-r2, ssp-3.4.6-1.0, pie-8.7.9)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

rip_someday ()
Ответ на: Re: Программистские перлы от hard_sintex

Re: Программистские перлы

>Первое что попалось под руку - gcc version 3.4.2 (mingw-special) - >выдало 0

Каким образом? Теоретически чётко определено, что присваивание имеет более низкий приоритет по сравнению с арифметическими операциями. Компилятор, что полностью положил на инкремент?????

Видать очень спешиал едишн.....

anonymous ()
Ответ на: Re: Программистские перлы от anonymous

Re: Программистские перлы

в спеке написано что-то типа, что компилятор гарантирует только получение результата выражения до его использования. порядок и время применения побочных эффектов не установлен.

anonymous ()
Ответ на: Re: Программистские перлы от rip_someday

Re: Программистские перлы

>> (i += ++i)++; - gcc выдаст 3.

> rip@riphome ~ $ echo 'int main() {int i=0;(i+=i++)++;return i;}'... > 2

ммм... У тебя инкремент другой используется. Ну вообще-то, да, я использовал g++ - и что (i = ...) вернет ссылку на i - даже не подозревал, что такое получится. Кстати - наверное дело в ссылках - в C их нету - поэтому (i = ...) ничего вернуть и не сможет - а без такой возможности конструкции вида

cout << "bla-bla == " << i << endl;

точно не смогли бы работать.

Spectr ★★★ ()
Ответ на: Re: Программистские перлы от rip_someday

Re: Программистские перлы

>мой результат тоже бред? :)

да. в первом случае. Видать оптимизации/версия компилятора кривые.

Во втором у тебя другое выражение.

anonymous ()
Ответ на: Re: Программистские перлы от anonymous

Re: Программистские перлы

>да. в первом случае. Видать оптимизации/версия компилятора кривые.

по умолчанию оптимизация -О0. в стандарте (не совсем такое же выражение как у нас, но достаточно похожее):

Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored. The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full expression; otherwise the behavior is undefined. [Example:

i = v[i++]; // the behavior is unspecified i = 7, i++, i++; // i becomes 9

i = ++i + 1; // the behavior is unspecified i = i + 1; // the value of i is incremented

--- end example]

а gcc 4.1.1 выдал единицу :)

>Во втором у тебя другое выражение.

во втором это к товарищу, утверждающему, что (i+=++i)++ будет 3. (а в С это даже не компилируется, как и показано выше).

rip_someday ()
Ответ на: Re: Программистские перлы от Spectr

Re: Программистские перлы

>ммм... У тебя инкремент другой используется.

каюсь. провтыкал.

>Ну вообще-то, да, я использовал g++ - и что (i = ...) вернет ссылку на i - даже не подозревал, что такое получится. Кстати - наверное дело в ссылках - в C их нету - поэтому (i = ...) ничего вернуть и не сможет - а без такой возможности конструкции вида

ес-но. в С оно не соберается. :)

rip_someday ()
Ответ на: Re: Программистские перлы от anonymous

Re: Программистские перлы

При чём тут приоритеты? i++ это оператор с side-effect, компилятор имеет право ставить его куда хочет между двумя ;, грубо говоря.

В общем не позорьтесь :) i = i++ - результат неопределен, спорить здесь не о чем.

Legioner ★★★★★ ()
Ответ на: Re: Программистские перлы от Legioner

Re: Программистские перлы

>При чём тут приоритеты? i++ это оператор с side-effect, компилятор имеет право ставить его куда хочет между двумя ;, грубо говоря.

т.е если

i=0; j=0; j=++i;

то возможно, что j=0 ??

Вроде некорректно изменять значение одной переменной больше одного раза "между двумя ;" Глупое и не очень логичное это требование, благо без таких кривостей можно и нужно обходиться. Многие компиляторы закрывают на это глаза и обрабатывают такое логически верно.

anonymous ()

Re: Программистские перлы

Странно, что никто до сих пор не вспомнил:

int i = 5;

int a = i++ + i++;

:)

Все известные мне языки с этой нотацией выдают, как следует из логики записи, выдают 11. И только Си/Си++ - 12 :)

KRoN73 ★★★★★ ()
Ответ на: Re: Программистские перлы от anonymous

Re: Программистские перлы

Нет, здесь j = 1
Когда ты пишешь i = i++
то это можно рассмотреть как
t = i;
i = t;
i = i + 1; /* side effect */
последние 2 инструкции могут идти в любом порядке. В каком они будут идти, такой и будет результат.
Если j = i++, то
t = i;
j = t;
i = i + 1; /* side effect */
Здесь уже разницы нет, результат всегда будет один и тот же.

Legioner ★★★★★ ()
Ответ на: Re: Программистские перлы от KRoN73

Re: Программистские перлы

Неправда ваша. Здесь результат опять же неопределён :) MSVC++ выдаёт здесь 10.

Legioner ★★★★★ ()
Ответ на: Re: Программистские перлы от rip_someday

Re: Программистские перлы

Единственный здравый человек, вспомнивший про Стандарт и sequence points.

Relan ★★★★★ ()
Ответ на: Re: Программистские перлы от Legioner

Re: Программистские перлы

>Нет, здесь j = 1 >Когда ты пишешь i = i++ >то это можно рассмотреть как >t = i; >i = t; >i = i + 1; /* side effect */

Интересно хоть один компилятор ворнинг об этом пишет? А то обычно просто 1 получается и всё.

anonymous ()

Re: Программистские перлы

Дискуссия наглядно показывает "синтаксический терроризм" языков группы СИ...

В языках группы Алгола (Паскаль, Модула, Оберон, Ада) таких казусов не наблюдается.

P.S. Си-звращенцам: "только не надо брызгать слюной!"

quickquest ★★★★★ ()
Ответ на: Re: Программистские перлы от quickquest

Re: Программистские перлы

это позволяет применять оптимизации, недоступные для языков группы алгола. Впрочем С никогда не был изящным языком, это машиннонезависимый ассемблер, и те, кто пишут на нём, должны понимать, что в ногу себе выстрелить очень просто. Впрочем как правило мозгов хватает не писать подобные глупости, и всё работает как надо.

Legioner ★★★★★ ()
Ответ на: Re: Программистские перлы от quickquest

Re: Программистские перлы

>Дискуссия наглядно показывает "синтаксический терроризм" языков группы СИ...

Это точно. С одним единственным оператором сколько извратов уже сочинили.

anonymous ()
Ответ на: Re: Программистские перлы от Legioner

Re: Программистские перлы

> Впрочем как правило мозгов хватает не писать подобные глупости, и всё работает как надо.

Если бы! Вот так некоторые наоптимизируют, а потом сидят часами в дебаггере.

anonymous ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.