Задачка с башорга

romy4

invoke [brain]
algo
в Си, в отличии от ПХП, подставляется адрес переменной, а не ее значение. на асме, сгенереном из такого кода это выглядело б примерно так:
Код:
mov [i],5 ;заносим по адресу переменной i 5
inc [var_i]   ; увеличиваем значение по адресу на 1 (++i)
inc [var_i]
mov ax,[var_i] ;берем левое значение возле знака +
mov dx,[var_i] ;берем правое значение возле знака +
add ax,dx ;складываем их
mov [var_i],ax ;заносим в переменную i получившееся значение
 

Сергей Тарасов

Профессор
Интересно то, что

#include<iostream>

int main(int argc, char** argv[])
{
int i = 5;
i = ++i;
std::cout << i << " ";
i+= ++i;
std::cout << i;
return 0;
}


выводит 6 14

-~{}~ 14.05.07 13:18:

Хотя тут вроде все понятно:
++i вычисляется раньше, чем i+=, поэтому получается 7+7
 

Фанат

oncle terrible
Команда форума
romy4
какой код в пхп дает 6 и 14?

Сергей Тарасов
В каком именно случае?
 

Сергей Тарасов

Профессор
#include<iostream>

int main(int argc, char** argv[])
{
int i = 5;
i = ++i + ++i;
std::cout << i;
return 0;
}

Хотя теперь все понятно...
i - это одна переменная для компилятора. У нее есть 1 адрес:
1) Делеаем инкремент. Получаем 6
2) Делаем еще раз инкремент. Получаем 7
3) Складываем. Получаем 14

Так в gcc. С точки зрения оптимизации - хорошо. С точки зрения соблюдения стандарта языка c - не знаю... :)
 

Vladson

Сильнобухер
Автор оригинала: Сергей Тарасов
Хотя теперь все понятно...
i - это одна переменная для компилятора. У нее есть 1 адрес:
1) Делеаем инкремент. Получаем 6
2) Делаем еще раз инкремент. Получаем 7
3) Складываем. Получаем 14

Так в gcc.
в Borland Turbo C++ тоже так

(если быть точным то вот кусок кода)
Код:
;
; int i = 5;
;
mov si,5
;
;i = ++i + ++i;
;
inc si
inc si
mov ax,si
add ax,si
mov si,ax
 

romy4

invoke [brain]
все компиляторы, выдющие 13 можно заносить в черный список :)
 

Фанат

oncle terrible
Команда форума
Сергей Тарасов
Стандарты, по словам дискуссий, как раз рекомендуют избегать применения таких неоднозначных конструкций.
 

Сергей Тарасов

Профессор
romy4

Скорее, наоборот, в gcc это плата за оптимальность, ибо с т.зрения теории программирования(функционального, императивного - какого угодно) должно быть 13

Фанат
Понятно, что стоит избегать.
 

Фанат

oncle terrible
Команда форума
Я писал не про то что следует избегать, а про то, что говорят стандарты отвечал на твой вопрос.
с чужих слов, правда.
 

dark-demon

d(^-^)b
нет никакой "теории всея программирования" :) есть конкретные языки и конкретные интерпретаторы.
и давайте мы не будем приписывать одному из древнейших языков какие-то баги на основании того, что некоторые(!) его подражатели делают что-то по другому.
 

romy4

invoke [brain]
Сергей Тарасов
ну это спорный момент
так как по логике (моей конечно же) операции имеющие высший приоритет должны выполнятся в первую очередь. Это раз. И два, то что подстановка значений должна происходить в последнюю очередь из переменных. т.е. фактически использоваться ссылки на переменные, а не копии их значений. вот.

да и это не только в gcc так :) мой любимый ватком дает тоже рузультат 14.
 

Сергей Тарасов

Профессор
По поводу самой задачки: кто-нить может проверит в VisualStudio?
Тем, кто питает иллюзии, что багов в gcc нет - ошибается.

-~{}~ 14.05.07 15:26:

Автор оригинала: dark-demon
нет никакой "теории всея программирования" :) есть конкретные языки и конкретные интерпретаторы.
и давайте мы не будем приписывать одному из древнейших языков какие-то баги на основании того, что некоторые(!) его подражатели делают что-то по другому.
По поводу этого:

1) Есть теория программирования (Функционального, Эмпирического и т.п.)
2) Есть Стандарт языка c++, который, Рома (!), должен оговаривать такие ситуации. Если он не разрешает такие неоднозначности - это плохой стандарт и его нужно исправить.
3) Есть компиляторы в той или иной мере соответствующие этому стандарту.

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