2012-01-25 4 views
0

Может ли кто-нибудь объяснить мне вывод следующего. Я попытался все рассуждать и могу объяснить более позднюю часть, где «x» присваивается значение выражения, но не может понять, как ответ отличается в заявлении printf !!!унарные операторы в printf

Различные компиляторы могут вести себя по-разному. Было бы здорово, если бы кто-нибудь мог объяснить это поведение для любого компилятора.

Я использую GCC (SUSE Linux) 4.6.2 на OpenSUSE 12.1 (Asparagus) (i586)

код:

#include<stdio.h> 

int main() 
{ 
unsigned int x=0; 
printf("expr= %d x=%d\n",(x^x),x); 
printf("x=%d\n",x); 
x=0; 
printf("expr= %d x=%d\n",(x^x)||x++,x); 
printf("x=%d\n",x); 
x=0; 
printf("expr= %d x=%d\n",(x^x)||x++||++x,x); 
printf("x=%d\n",x); 
x=0; 
printf("expr= %d x=%d\n",(x^x)||x++||++x||x++,x); 
printf("x=%d\n",x); 
x=0; 
printf("expr= %d x=%d\n",x++,x); 
printf("x=%d\n",x); 
x=0; 
printf("expr= %d x=%d\n",++x||x++,x); 
printf("x=%d\n",x); 
x=0; 
printf("expr= %d x=%d\n",x++||++x||x++,x); 
printf("x=%d\n",x); 
x=0; 
printf("expr= %d x=%d\n",(x^x)||x++||++x||x++,x); 
printf("x=%d\n",x); 
x=0; 
(x^=x); 
printf("x=%d\n",x); 
x=0; 
(x^=x)||x++; 
printf("x=%d\n",x); 
x=0; 
(x^=x)||x++||++x; 
printf("x=%d\n",x); 
x=0; 
(x^=x)||x++||++x||x++; 
printf("x=%d\n",x); 

return 0; 
} 

выход:

expr= 0 x=0 
x=0 
expr= 0 x=1 
x=1 
expr= 1 x=2 
x=2 
expr= 1 x=2 
x=2 
expr= 0 x=1 
x=1 
expr= 1 x=1 
x=1 
expr= 1 x=2 
x=2 
expr= 1 x=2 
x=2 
x=0 
x=1 
x=2 
x=2 

Благодаря

+1

Это код. Пожалуйста, укажите **, которые ** вы не понимаете (еще лучше, просто удалите все, что вы понимаете). –

+1

Я постоянно удивляюсь количеству сдвигов людей, которые хотят до и после увеличивать переменную между точками последовательности ... почему? –

+1

@EdS .: '||' - это точка последовательности. –

ответ

4

Вы ссылаетесь на неуказанное поведение.

В выражении типа func(a,b) в стандарте C не указывается, какой аргумент должен быть оценен первым; компилятор также может это сделать.

Теперь рассмотрим func(x++,x); это не определено, является ли это эквивалентно следующему:

a = x++; 
b = x; 
func(a,b); 

или это:

b = x; 
a = x++; 
func(a,b); 
+0

Вот почему у меня также есть printf («% d \ n», x) после каждого printf («expr =% d x =% d», «expr», x), чтобы подтвердить это. Похоже, что результат согласован. – ntalli

3
printf("expr= %d x=%d\n",(x^x)||x++||++x,x); 

Эта функция показывает неопределенное поведение. Порядок оценки между (x^x)||x++||++x и x не указан.

Большинство других printf вызовов в вашей программе имеют ту же проблему.

(С99, 6.5.2.2) «Порядок оценки функционального назначения, фактические аргументы, и подвыражения в пределах фактических аргументов не определена, но существует точка последовательности до фактического вызова.»

Программа, выход которой зависит от неуказанного поведения, не является строго соответствующей программой (см. C99, 4.p5).

+0

Вот почему у меня также есть printf («% d \ n», x) после каждого printf («expr =% d x =% d», 'expr', x), чтобы подтвердить это. Похоже, что результат согласован. – ntalli

+1

@ user1170267 вывод может быть совместим с вашим компилятором, но поскольку это неопределенное поведение, оно может быть другим с другой версией одного и того же компилятора или даже с одним и тем же компилятором, но в другой день недели. – ouah

+0

позволяет сказать, что меня просто касается printf ("expr =% d \ n", (x^x) || x ++ || ++ x || x ++) ..... и (x^= x) | | x ++ || ++ x || x ++) на данный момент. – ntalli

Смежные вопросы