C препроцессоры и порядок операций - PullRequest
9 голосов
/ 27 апреля 2011

Я изучаю C, но я не понимаю этого:

#define square(x) x*x
a = square(2+3) //a = 11

Когда это выполняется, почему a в итоге становится 11?

Ответы [ 5 ]

21 голосов
/ 27 апреля 2011

Расширяется до 2+3*2+3, что эквивалентно 2+(3*2)+3. Используйте скобки, чтобы исправить это:

#define square(x) ((x)*(x))

Теперь попробуйте это с square(x++), и вы столкнетесь с большим количеством проблем (неопределенное поведение). Избегайте делать это как макрос, если можете.

12 голосов
/ 27 апреля 2011

square(2+3) расширяется до 2+3*2+3, что эквивалентно 2+(3*2)+3 [* имеет более высокий приоритет, чем +]

В gcc вы можете использовать опцию -E, чтобы увидеть, какой у вас препроцессоргенерирует

C:\Users\SUPER USER>type a.c
#define square(x) x*x

int main()
{
   a = square(2+3); //a = 11
}

C:\Users\SUPER USER>gcc -E a.c
# 1 "a.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "a.c"


int main()
{
   a = 2+3*2+3;
}

Средство устранения

Попробуйте это

#define square(x) ((x)*(x))
1 голос
/ 27 апреля 2011

Попробуйте:

#define square(x) ((x)*(x))
1 голос
/ 27 апреля 2011

Поскольку 2 + 3 подставляется буквально в выражении x * x, оно становится 2 + 3 * 2 + 3, а оператор * имеет более высокий приоритет, поэтому вы не получите ожидаемый результат.

Всегдазаключите аргументы макроса и все выражение в круглые скобки, чтобы избежать этого:

#define SQUARE(x) ((x) * (x))

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

0 голосов
/ 27 апреля 2011

подумайте, что вы получите, когда макрос развернут.Препроцессор c расширит это как

a = 2 + 3 * 2 + 3

Вы должны правильно определить свой макрос.Всегда заключайте макрос в круглые скобки.Это даст вам ожидаемый результат.

#define square(x) ((x)*(x))

Расширение макроса будет следующим:

a = ((2 + 3) * (2 + 3))
...