Использование вложенных макросов в C - PullRequest
3 голосов
/ 14 августа 2011
#include "stdafx.h"
#include<stdio.h>

#define PR(x) printf("%d\t",(int)(x));
#define PRINT(a,b,c) PR(a) PR(b) PR(c)
#define MAX(a,b) (a<b?b:a)

int main()
{
    int x=1,y=2;
    //PR(MAX(x++,y));
    PRINT(MAX(x++,y),x,y);  //2,2,2
    PRINT(MAX(x++,y),x,y);  //2,3,2
    return 0;
}

x равно 1, поэтому 3 значения, передаваемые в PRINT, равны 2 2 2.

Тогда во втором PRINT значения, которые будут переданы, равны 2 3 2. Таким образом, вывод должен быть 2 2 2 2 3 2. Но эта программа выводит как 2 2 2 3 4 2.

Ответы [ 4 ]

7 голосов
/ 14 августа 2011

Ваш MAX макрос плох. Он оценивает один из своих аргументов дважды.

 MAX(x++,y)

расширяется до:

 (x++ < y ? y : x++)
                ^^^

Таким образом, x увеличивается в два раза, если он начинался меньше y.

В этом коде нет неопределенного поведения, потому что существует точка последовательности между вычислением первой части троичного оператора и выбранной части. Все выражение PRINT расширяется до:

 printf("%d\t", (x++ < y ? y : x++));
 printf("%d\t", (x));
 printf("%d\t", (y));

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

5 голосов
/ 14 августа 2011

У ваших макросов есть несколько проблем:

  • Никогда не скрывайте ; внутри макроса, но ведите себя как обычный Заявление
  • Не пишите макросы, которые оценивают свои аргументы несколько раз
  • всегда ставьте скобки вокруг параметров макроса так, чтобы вы знали приоритет всех операторов.
3 голосов
/ 14 августа 2011

Ваш MAX(x++,y) вызов преобразуется в (x++<y?y:x++) и приводит к двойной модификации x во время первого вызова.

1 голос
/ 14 августа 2011

PRINT ((MAX (x ++, y), x, y) -> PR (MAX (x ++, y)) PR (x) PR (y) -> PR (x ++

х = 1, у = 2 Имеет ли PR (2 с 1 <2) и увеличивает x до 2 Тогда PR (2) PR (2) - отсюда выведите 2 2 2 </p>

Next PR (MAX (x ++ (ie2) <2 - false)? 2: x ++ (то есть использовать увеличенное значение x из условия (3), затем вывести 3 и увеличить x до 4) - следовательно, x увеличивается дважды) </p>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...