VS .NET Compiler

tosha01

Кто может объяснить разницу ?
#include <stdio.h>
int main(void)
{
int i=0 ,j=0;
int *pi=&i;
printf (" i : %d %d %d \n", ++i, i++, ++i);
printf (" j : %d %d %d \n", ++j, j++, ++j);
return 0;
}
результат работы
(релиз, дебаг - одна фигня)
i : 3 1 3
j : 2 1 2

onairika

У меня вс 6.0 выдаёт
i : 2 1 1
j : 2 1 1
то есть то что и должно быть

Chupa

Результат дизассемблирования в студию!

otets-mihail

i : 3 1 1
j : 3 1 1
gcc 3.2

otets-mihail

VCPP.NET
i : 3 1 3
j : 3 1 3

oleg701

А вам никто и никогда не советовал не использовать ++ в printf, потому что это неспецифированная функция? То есть для нее не гарантируется порядок обработки параметров...

oleg701

Хотя разница все равно не понятна...

1111! Чуть не пропустил

otets-mihail

И напоследок аналогичное в C#
i : 1 1 3
j : 1 1 3

onairika

Ну то что в разных компиляторах по разному ето фиг с ним просто по разному выражения разбирают. Странно что у госта разные для i и j ответы получились

otets-mihail

++posts чуть не пропустил...

spirtus

Маза единственный компилятор который дает предсказуемый (а значит единственно правильный в данном случае результат) - это GCC, в 2.95 такой же конечно.
MS - suxx

zsn66

Маза не существует в данном случае единственно правильного результата. Перцу, который пишет подобное в реальной программе, нужно руки обрывать.

spirtus

естественно писать так не стоит, но за GCC можно порадоваться.

nataliagood

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

Pchela2008

Не странно. &i видел? Почти уверен, что j соптимизировано в регистр, а i используется из памяти.

zsn66

gcc 2.95 делает так:
pushl $1
pushl $1
pushl $3
pushl $.LC0
call printf
pushl $1
pushl $1
pushl $3
pushl $.LC1
call printf
Обходится и без регистров, и без памяти.

Pchela2008

верх оптимизации Сразу положить уже результат вычислений.
Но я-то отвечал на то, почему у i и j разные результаты получаются

zsn66

Потому что не делаются соостветствующие выводы из того, что pi после инициализации не используется. А вот почему - то ли ума не хватает, то ли так и задумано - это надо обращаться к разработчику

Pchela2008

Ну насколько я помню это, например, используется даже в том же gcc. В качестве предотвращения порчи значений переменных при том же vfork info gcc рекомендует либо volatile, либо (для совместимости со старыми компиляторами) (void)&i; - взятие адреса. Чтобы избежать оптимизации в регистр.

Dasar

Стандарт говорит, что так делать нельзя, а если все-таки сделать, то результат - неопределен (undefined behaviour). и компилятор может делать все что угодно, хотя винт форматировать.
Оставить комментарий
Имя или ник:
Комментарий: