2014-09-13 2 views
-5

Следующая программа печати 49неправильный ответ от #define SQR (х) (х * х)

#include <stdio.h> 
#define SQR(x) (x*x) 
void main(void) { 
    int x, y; x = 5; 
    y = SQR(++x); 
    printf("y is %d\n", y); 
} 

Я не понимаю, что мне не хватает.
Вот что я понять, как это могло бы работать
В SQR(++x), ++x будет оценено как 6 и после x*x36 должны быть возвращены.
Поэтому y = 36
Но ответ

+2

Подумайте, как работают макросы и сколько раз вычисляется выражение. –

+0

@Matt: нет, это не определено как таковое. – usr2564301

+0

@Jongware да это –

ответ

5

Прочитайте wikipage о C preprocessor и поймите, что препроцессор C работает на чисто текстовом уровне (в качестве первой фазы компилятора). Читайте также документацию GNU cpp. Ваш y = SQR(++x); расширяется в

y = ++x * ++x; 

Который не то, что вы должны хотеть. Читайте о undefined behaviorthis answer). Подумайте об ужасах, происходящих (используя ваш оригинал SQR) с SQR(y+3).

Посмотрите на предварительно обработанную форму исходного кода. С GCC, используйте

gcc -C -E foo.c > foo.i 

получить в foo.i (который вы должны изучить с помощью редактора или пейджера) в препроцессоре виде foo.c

Так, по крайней мере, вы должны определить макрос, как

#define SQR(x) ((x)*(x)) 

В противном случае SQR(y+3) не будет расширяться, как вы хотите. В общем, при использовании макроса вы должны знать (и документировать, например, в комментарии, если вы пишете макрос), что происходит.

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

static inline int square(int x) { return x*x; } 

это будет так быстро, как макрос, но гораздо более безопасным, так как square(++x) прирост будет (правильно) x только один раз, и square(y+3) делает, что вы хотите!

2

Помните, что макросы заменяются почти дословно, это означает, что ваш

SQR(++x); 

будет заменен

++x * ++x; 

и, как отмеченный dyp, это неопределенное поведение.

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