Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 无法获取宏和运算符优先级背后的逻辑_C_C Preprocessor - Fatal编程技术网

C 无法获取宏和运算符优先级背后的逻辑

C 无法获取宏和运算符优先级背后的逻辑,c,c-preprocessor,C,C Preprocessor,以下代码的输出为8 24 32。我理解8和24背后的逻辑,但32对我来说似乎很奇怪。有人能解释为什么它打印32吗 #define cube(x) x*x*x void main() { printf("%d ",cube(2)); printf("%d ",16+cube(2)); printf("%d ",16/cube(2)); } 宏只是text1的编译时替换。因此C预处理器将更改这一行: printf("%d ",16/cube(2)); printf("%

以下代码的输出为8 24 32。我理解8和24背后的逻辑,但32对我来说似乎很奇怪。有人能解释为什么它打印32吗

#define cube(x) x*x*x
void main()
{
    printf("%d ",cube(2));
    printf("%d ",16+cube(2));
    printf("%d ",16/cube(2));
}

宏只是text1的编译时替换。因此C预处理器将更改这一行:

 printf("%d ",16/cube(2));
printf("%d ", 16/2*2*2);
关于这一行:

 printf("%d ",16/cube(2));
printf("%d ", 16/2*2*2);
完成此文本替换后,编译器将检查表达式。这将导致以下评估:

// 16/2 is evaluated first because '/' has the same precedence as '*',
// so the tie is broken by left-to-ride order:
printf("%d ", 8*2*2);

// Then each of the '*' operators is evaluated in turn:
printf("%d ", 16*2);
printf("%d ", 32);
通常建议在每次使用宏参数和整个宏定义周围使用括号,以防止运算符优先级改变宏中表达式的解释方式:

#define cube(x) ((x)*(x)*(x))
请注意,如果多维数据集不是宏而是函数,则结果会有所不同,因为函数在传递参数之前已完全编译:

int cube (int x)
{
   return x*x*x;
}
…
printf("%d ",16/cube(2)); // Prints 2.
脚注 1实际上,文本被解析为预处理器标记,可能会出现其他一些语法问题。在很大程度上,宏替换是文本替换,但可能会有一些复杂情况。

最后一个printf被转换为:

printf("%d ",16/2 * 2 * 2);
这就是为什么所有宏都应该有圆括号的原因:

#define cube(x) ((x)*(x)*(x))

或者只使用函数并信任编译器内联它们。函数几乎总是更好。

因为多维数据集是一个宏

16/cube(2)
通过预处理器计算以

16/2*2*2
一共32个

如果需要宏而不是函数,请将输入和输出用括号括起来。e、 g

#define cube(x) ((x)*(x)*(x))

但是我在这里真的要使用一个函数。

如果您在gcc下,请使用-E编译以查看预处理器的输出

gcc -E demo.c > out.c

这可以帮助您下次使用宏时,我们应该非常小心。它看起来像一个函数,但实际上它不是一个函数。在编译时,预处理器只会在第一次使用宏时发现的任何地方展开宏

printf("%d ",cube(2)); expands into printf("%d",x*x*x); then it prints 8
printf("%d ",16+cube(2)); expands into  printf("%d",16+x*x*x); then it prints 24
printf("%d ",16/cube(2)); expands into printf("%d",16/x*x*x); but prints 32

有什么奇怪的?了解运算符关联性。阅读:为什么宏是邪恶的及其副作用。请参阅?你学到了三件事。1运算符优先级确实有意义,2始终围绕宏参数和带parens的最终表达式定义cubex*x*x,3不使用macros=Pvoid main是错误的,原因有两个:1。main返回int.2。与C++不同,C空括号不等于空格,但在K& R OLD样式中意味着固定但未指定的ARG数。@ Jens,你的最后一点不完整。在函数定义中,表示函数不接收参数。这不是一个函数原型,但仍然是有效的C。包装参数,并定义直接调用cpp的cubex x*x*xor。@Heisenbug,你是对的;运算符优先规则规定除法运算符在乘法之前求值?你说的是联想性吗?是一样的。通常,优先级和结合性是一致的:是的,但有人可能认为除法总是在乘法之前计算,因为优先级更高,但正如你所知,这不是真的。但也许只是我的英语不好我对此投了赞成票,因为它是目前唯一一个说明宏扩展是编译时替换的答案。其他人只是描述结果或解决方案,而没有解释这个简单的事实。但是,语言可以澄清。我将做一些编辑,也许是增加大胆。请随时回复。