Weird macro definition issue

与世无争的帅哥 提交于 2019-12-24 23:33:03

问题


I want to define a macro at compile time based on the value of another macro. However this code is not executing as expected:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIXTEEN 16
#define TWO (SIXTEEN % 8 == 0)? (SIXTEEN / 8) : ((SIXTEEN / 8) + 1)

int main();

int main() {
    printf("max = %d\n", TWO);
    int i;
    for (i = 0; i < TWO; i++) {
        printf("%d\n", i);
    }
    return 0;
}

This prints:

max = 2
0
1
2
...

and continues until terminated, When it should be printing simply:

max = 2
0
1

and exiting.

If I do this instead, it works:

#define TWO 2

I thought that this was an issue with the macro's definition... however, if I do the following with the original #define, it seems to work:

...
int count = TWO;
for (i = 0; i < count; i++) {
...

Can anyone explain what's going on here?


回答1:


The problem is that the token TWO is replaced by the tokens with which you defined the macro, so this:

i < TWO

becomes this:

i < (SIXTEEN % 8 == 0)? (SIXTEEN / 8) : ((SIXTEEN / 8) + 1) 

Because of operator precedence, this is read as:

(i < (SIXTEEN % 8 == 0))
    ? (SIXTEEN / 8) 
    : ((SIXTEEN / 8) + 1) 

You need extra parentheses so that when TWO is replaced by its replacement list, you get the result you want:

#define TWO ((SIXTEEN % 8 == 0)? (SIXTEEN / 8) : ((SIXTEEN / 8) + 1))
            ^                                                       ^

When using macros, it's best to use parentheses wherever you can to ensure the result is what you expect.




回答2:


Always enclose macros in parentheses because you don't always know the context in which it will be used - it could happen that an adjacent operator has a higher precedence and the macro will not evaluate correctly.

Not using parentheses is only justified if the #define'd symbol is a single token, such as 5 or "hello world".

If you consider calling your macro with arguments that are expressions and not just single tokens, enclose every occurrence of that argument in parentheses for the same reason as above.

Another thing to avoid is passing expressions that have side effects as macro arguments. If the corresponding macro argument is referenced more than once in its definition, the evaluation will be performed more than once, and that usually isn't what's desired.




回答3:


Expand the macro, and look at your for loop after the macro expansion:

for (i = 0; i < (16 % 8 == 0)? (16 / 8) : ((16 / 8) + 1); i++)

See? i < (16 % 8 == 0) is the condition of the ?: operator. You need to put a pair of parenthesis around the definition of TWO.



来源:https://stackoverflow.com/questions/4455307/weird-macro-definition-issue

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!