如何评估此C预处理器?

-5 c macros c-preprocessor

#include<stdio.h>
#define SQUARE(x) x*x
int main(){
float s=10,u=30,t=2,a;
a=2*(s-u*t)/SQUARE(t); // How is this evaluated ? 
printf("Result %f\n",a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译器显示的输出为-100.000000.但据我说它应该是-25.000000.我该怎么做才能纠正它,我的错误是什么?

lur*_*ker 5

#define对您定义的字符串进行文字替换.所以表达式:

 a = 2*(s-u*t)/SQUARE(t*t)
Run Code Online (Sandbox Code Playgroud)

将扩展为:

 a = 2*(s-u*t)/t*t
Run Code Online (Sandbox Code Playgroud)

根据运营商的评估顺序,评估为:

a = (2*(s-u*t)/t)*t
Run Code Online (Sandbox Code Playgroud)

不是你想要的.你可能真的想要a = 2*(s-u*t)/(t*t)这样你应该:

#define SQUARE(x) (x*x)
Run Code Online (Sandbox Code Playgroud)

甚至更好,正如@Jongware指出的那样,因为x它本身可能是一个表达式:

#define SQUARE(x) ((x)*(x))
Run Code Online (Sandbox Code Playgroud)

这样,像这样的表达式SQUARE(a+b)将正确评估((a+b)*(a+b)),而不是(a+b*a+b).

同样如评论中所指出的,当您在参数中有副作用时,您需要注意宏表达式结果.例如,做SQUARE(x++)什么,什么x时候完成它的价值?在这种情况下,它会给出后两次递增(x++)*(x++)的值,x结果可能是未定义的行为(在这种情况下取​​决于后增量的顺序).

  • 曾经如此安全:`#define SQUARE(x)((x)*(x))`.它将删除(仅)一个可能的陷阱:`SQUARE(1 + 2)`. (4认同)
  • `SQUARE(x ++)`导致UB,对吧?两个增量之间没有序列点...... (2认同)