C宏行为

时间:2013-06-09 06:31:07

标签: c macros

我有简单的以下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。

感谢。

8 个答案:

答案 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 + 110 + 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