LINUX.ORG.RU
ФорумTalks

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


0

0

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

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

y = x/sqrt(x);

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

i=0;

i= i++;

i=?

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

:)

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

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

Cris
()

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

cvb
()

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

0 или 1

Legioner ★★★★★
()

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

asgard
()

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

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

annoynimous ★★★★★
() автор топика
Ответ на: комментарий от dilmah

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

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

annoynimous ★★★★★
() автор топика
Ответ на: комментарий от onanyzmus

>i++ вначале возвращает, потом инкрементирует. Поэтому 0

неверно, всё наоборот произойдёт и будет i=1.

anonymous
()

gcc выдал 1 :)

anonymous
()

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

record ★★★★★
()
Ответ на: комментарий от annoynimous

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

>j=i++;

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

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

Всё верно.

anonymous
()
Ответ на: комментарий от annoynimous

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

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

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

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

Spectr ★★★
()
Ответ на: комментарий от anonymous

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

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

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

soomrack ★★★★
()
Ответ на: комментарий от anonymous

>i= i++;

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

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

anonymous
()
Ответ на: комментарий от anonymous

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

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

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

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

GPFault ★★
()
Ответ на: комментарий от GPFault

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

anonymous
()

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

hard_sintex
()
Ответ на: комментарий от anonymous

>Тогда хочу видеть реализацию, где результат будет не 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
()
Ответ на: комментарий от hard_sintex

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

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

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

anonymous
()
Ответ на: комментарий от anonymous

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

anonymous
()
Ответ на: комментарий от rip_someday

>> (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 ★★★
()
Ответ на: комментарий от rip_someday

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

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

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

anonymous
()
Ответ на: комментарий от anonymous

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

по умолчанию оптимизация -О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
()
Ответ на: комментарий от Spectr

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

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

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

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

rip_someday
()
Ответ на: комментарий от anonymous

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

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

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

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

т.е если

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

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

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

anonymous
()

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

int i = 5;

int a = i++ + i++;

:)

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

KRoN73 ★★★★★
()
Ответ на: комментарий от anonymous

Нет, здесь 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 ★★★★★
()
Ответ на: комментарий от KRoN73

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

Legioner ★★★★★
()
Ответ на: комментарий от rip_someday

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

Relan ★★★★★
()
Ответ на: комментарий от Legioner

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

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

anonymous
()

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

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

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

quickquest ★★★★★
()
Ответ на: комментарий от quickquest

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

Legioner ★★★★★
()
Ответ на: комментарий от quickquest

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

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

anonymous
()
Ответ на: комментарий от Legioner

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

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

anonymous
()
Ответ на: комментарий от dilmah

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

долго втыкал что это такое =)

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