当用作较大数学表达式的一部分时,使用宏导致错误输出 - 为什么会发生这种情况?

时间:2010-01-22 04:58:08

标签: c macros

这是一个正常的C例行程序,我在一些问题库中找到了。如下所示:

#define CUBE(p) p*p*p

main()
{
    int k;
    k = 27 / CUBE(3);
    printf("%d", k);
}

根据我的理解和知识,K的值应为1,因为在预处理期间CUBE(3)将被3 * 3 * 3替换,并且在随后的编译之后它将给出值1,但它具有显示了81的值,这让我很想知道它是如何发生的。

任何人都可以证明上述问题的答案是正确的。

13 个答案:

答案 0 :(得分:15)

预处理器仅替代

CUBE(3)

3*3*3

所以你最终得到:

k=27/3*3*3

其中,从左到右评估运算符优先级,实际上是81。

如果在宏周围添加括号,您应该会发现结果是正确的:

#define CUBE(p) (p*p*p)

用括号括起p的每个实例会更好,如:

#define CUBE(p) ((p)*(p)*(p))

这将允许您正确地将表达式传递给宏(例如,1 + 2)。

答案 1 :(得分:4)

由于运营商优先级27/3*3*3 = 81

你可以改用:

inline int cube(int p) { return p*p*p; }

答案 2 :(得分:3)

预处理器应正确括号。替换为

#define CUBE(p) ((p)*(p)*(p))

并看到。

答案 3 :(得分:2)

C宏进行文本替换(即它相当于复制和粘贴代码)。所以你的代码来自:

k=27/CUBE(3);

k=27/3*3*3;

除法和乘法具有相同的优先级并具有从左到右的关联性,因此将其解析为:

k=((27/3)*3)*3;

是9 * 3 * 3 = 81。

这就是为什么C宏应该总是通过自由使用括号来定义:

#define CUBE(p) ((p) * (p) * (p))

有关详细信息,请参阅comp.lang.c常见问题解答中的http://c-faq.com/cpp/safemacros.html

答案 4 :(得分:2)

因为宏是一个文本替换,所以它适用于:

k = 27 / 3 * 3 * 3;

由于乘法和除法从左到右发生,因此可以解决:

k = ((27 / 3) * 3) * 3;

所以,你想以两种方式改变它:

#define CUBE(p) ((p)*(p)*(p))

外括号使得乘法在任何其他操作之前完成。

个别p周围的括号适用于您的情况:

CUBE(1 + 2);

如果没有这些内部括号,运算符优先级将使您失望。

答案 5 :(得分:1)

您的宏未受保护。试试

#define CUBE(p) ((p)*(p)*(p))

当前的宏已扩展为

k=27/3*3*3

是((27/3)* 3)* 3

答案 6 :(得分:0)

     #define CUBE(p) p*p*p
     main()
     {
        int k;
        k=27/CUBE(3);
        printf("%d",k);

     }
  

根据我的理解和知识,K的值应为1,因为在预处理期间CUBE(3)将被3 * 3 * 3替换

YES

  

并且在随后的编译之后它将给出值1,但它显示了81的值,这让我很好奇地知道它是如何发生的。

不,

k= 27/3*3*3 

 =(((27/3)*3)*3) (The precedence of `*` and `/` are same but the associativity is from left to right)
 =((9*3)*3) =81

#define CUBE(p) p*p*p替换为#define CUBE(p) ((p)*(p)*(p))

答案 7 :(得分:0)

k=27/CUBE(3);  =>   k=27/3 * 3 * 3;
你看到了吗? CUBE应该像这样定义:

#define CUBE(p) ((p)*(p)*(p))

答案 8 :(得分:0)

当你做宏时,你必须小心如何放置括号。在这种情况下,你没有任何,所以表达式变为27/3 * 3 * 3,由/和*的优先规则变为(27/3)* 3 * 3.

答案 9 :(得分:0)

27/3 * 3 * 3 = 9 * 3 * 3 = 81?

答案 10 :(得分:0)

两个/和*运算符具有相同的优先级。要先执行3 * 3 * 3,您应将它们括在括号中。

#include <stdio.h>

#define CUBE(p) p*p*p

int
main ()
{
  int k;
  k=27/(CUBE(3));
  printf("%d",k);
  return 0;
}

答案 11 :(得分:0)

它实现运算符的关联性和优先级的方式。 当表达式扩展时,它变成了 27/3 * 3 * 3而不是27 /(3 * 3 * 3) 现在,除法和乘法在C中具有相同的优先级,但两者的关联性从左到右。 所以它可以显示为: (27/3)* 3 * 3又等于(9 * 3)* 3 = 81 另外,如果你记得 BODMAS(Bracket Off Division Multiplication Addition Subtraction)的旧算术规则,这是优先顺序,那么我们首先进行除法然后再进行乘法运算。 所以我们再次以27/3 * 3 * 3得到81的答案。

答案 12 :(得分:0)

你好回答的是:81 说明: 在步骤k = 27 /立方体(3) 立方体(3)由预处理器替换为3 * 3 * 3.然后上述语句变为k = 27/3 * 3 * 3 在那个27/3表达式由c编译器(运算符优先级)评估 结果是(27/3):9 陈述k = 27/3 * 3 * 3变为k = 9 * 3 * 3; 上述陈述的结果是81: