我有简单的以下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。
感谢。
答案 0 :(得分:5)
首先,您的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
(把它放在头文件中)
答案 1 :(得分:3)
'cos
#define Sqrt(A) A * A
制作
Sqrt(A+1);
翻译为
A + 1 * A + 1
和A是10
所以你得到了
10 + 1 * 10 + 1
现在做数学!
BTW sqrt似乎说平方根不平整!
答案 2 :(得分:3)
您将宏定义为A * A
。因此,Sqrt(A + 1)
扩展为A + 1 * A + 1
,由于运算符优先级,等于2 * A + 1
- 您已获得2 * 10 + 1 = 21
。
这就是为什么你应该总是将你的宏和他们的论点括起来:
#define Sqrt(A) ((A) * (A))
顺便问一下,为什么一个宏?如果有一天你写Sqrt(A++)
怎么办?然后你可以期待nasal demons。编写内联函数会更安全(horribile dictu,正确命名的内联函数):
static inline double square(double x)
{
return x * x;
}
答案 3 :(得分:2)
在宏内部,A
被替换为传递给宏调用的内容。在这种情况下,即A+1
。这意味着宏将扩展为:
A+1 * A+1
由于运算符优先级,这被解释为A + 1*A + 1
或10 + 10 + 1 = 21
。
答案 4 :(得分:1)
您应该将宏定义为#define Sqrt(A) ((A) * (A))
答案 5 :(得分:0)
逐字取代宏,然后进行评估。
由于乘法的优先级高于添加,因此当您将A+1
提供给宏时,它会变为10 + 1 * 10 + 1
=> 10 + 10 + 1
=> 21
同样,如果您提供A+2
..... 10 + 2 * 10 + 2
=> 10 + 20 + 2
=> 32
。
答案 6 :(得分:0)
BODMAS统治伙伴!!正如先前的答案所示。乘法在添加之前进行。 你的操作Sqrt(A + 1),其中A = 10将评估为10 + 1 * 10 + 1 10 + 10 + 1 21 !!
答案 7 :(得分:0)
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