我有以下简单的 C 代码
#define Sqrt(A) A * A
int main(void) {
int A = 10;
int x = Sqrt(A+1);
return 0;
}
出于某种原因,当我这样使用它时,使用 A+1,我得到 x 为 21,这可能是 10+11。我的问题是,乘法是如何被忽略的?如果我用宏文本切换宏,我会得到正确的结果,即 121。
谢谢。
首先,你Sqrt
的名字错了,应该是Square
(不是平方根)
然后,生成预处理的表单(即使用gcc -C -E
)并查看其中的内容。
#define Sqr(A) A * A
int a = 10;
int x = Sqr(a+1);
最后一行扩展为
int x = a+1 * a+1;
被解析为
int x = a+(1*a)+1;
故事的寓意,总是在宏定义中使用额外的括号,即
#define Sqr(A) ((A)*(A))
即使有这样的定义,Sqr(a++)
也可能是未定义的行为,至少是顽皮的。
所以你想避免使用宏,实际上,学习使用内联函数,比如
inline int square(int a) { return a*a; };
static inline
顺便说一句,您不仅要使它inline
(并将其放在头文件中)
'cos
#define Sqrt(A) A * A
使
Sqrt(A+1);
翻译成
A + 1 * A + 1
A是10
所以你得到
10 + 1 * 10 + 1
现在做数学!
顺便说一句 sqrt 似乎说平方根不是平方的!
您将宏定义为A * A
. 因此,Sqrt(A + 1)
扩展为A + 1 * A + 1
,也就是说,由于运算符优先级,等于2 * A + 1
- 你有2 * 10 + 1 = 21
.
这就是为什么你应该总是给你的宏和它们的参数加上括号:
#define Sqrt(A) ((A) * (A))
顺便说一句,为什么是宏?如果有一天你写作Sqrt(A++)
呢?那么你可以期待鼻恶魔。写一个内联函数会更安全(可怕的 dictu,一个正确命名的内联函数):
static inline double square(double x)
{
return x * x;
}
在宏内部,A
替换为传递给宏调用的任何内容。在这种情况下,即A+1
。这意味着宏被扩展为:
A+1 * A+1
由于运算符优先级,这被解释为A + 1*A + 1
, 或10 + 10 + 1 = 21
。
您应该将宏定义为#define Sqrt(A) ((A) * (A))
BODMAS 规则哥们!!正如前面的答案所暗示的那样。乘法发生在你的加法之前。您的操作 Sqrt(A+1) 其中 A = 10 将计算为 10+1*10+1 10+10+1 21!!
when you call x = MACRO_NAME(A+1); this statement is replace as x = A + 1 * A + 1
in c priority of multiplication is more than addition so it will be 1st executed 1*A which give as A, then A+A+1 will give you result as 21`enter code here`
i.e A+1*A+1
= A+A+1
= 21
for proper answer you need to write Macro as #define MACRO_NAME(A) (A) * (A) which give you result as
121
宏被逐字替换,然后被评估。
由于乘法比加法具有更高的优先级,因此当您赋予A+1
宏时,它变为10 + 1 * 10 + 1
=> 10 + 10 + 1
=>21
同样,如果你给A+2
..... 10 + 2 * 10 + 2
=> 10 + 20 + 2
=> 32
。