使用#define时产生奇怪的mod运算符(%)

时间:2011-07-28 21:11:31

标签: c++ c-preprocessor modulo

int temp1,temp2,temp3;
temp1 = 199;
temp2 = 200;
temp3 = 199%temp2;

CString txt;
txt.Format(_T("temp3 = %d"),temp3);
AfxMessageBox(txt);

预期输出为199.

#define WIDTH 100
#define BUFFERWIDTH 200
int temp1,temp2,temp3;
temp1 = 199;
temp2 = BUFFERWIDTH;
temp3 = 199%BUFFERWIDTH;

CString txt;
txt.Format(_T("temp3 = %d"),temp3);
AfxMessageBox(txt);

预期输出为199.

#define WIDTH 100
#define BUFFERWIDTH 2*WIDTH
int temp1,temp2,temp3;
temp1 = 199;
temp2 = BUFFERWIDTH;
temp3 = 199%BUFFERWIDTH;

CString txt;
txt.Format(_T("temp3 = %d"),temp3);
AfxMessageBox(txt);

输出为100 ......

只是想知道造成这种情况的原因:)

9 个答案:

答案 0 :(得分:8)

了解operator precedence,并注意您说的是199 % 2 * 100

。 。

或者我应该说,(199 % 2) * 100 ......

答案 1 :(得分:4)

这是预处理器的典型问题。问题是,当你写

#define BUFFERWIDTH 2*WIDTH
temp3 = 199%BUFFERWIDTH;

预处理器将其扩展为

#define BUFFERWIDTH 2*WIDTH
temp3 = 199 % 2 * WIDTH;

请注意,这被解释为

temp3 = (199 % 2) * WIDTH;

而不是预期的

temp3 = 199 % (2 * WIDTH);

要解决此问题,您有多种选择。首先,您可以将BUFFERWIDTH的定义括起来,如下所示:

#define BUFFERWIDTH (2*WIDTH)
temp3 = 199%BUFFERWIDTH;

现在,这扩展到

temp3 = 199 % (2 * WIDTH);

正如所料。但是,更好的选择是使用const来定义常量:

const int BUFFERWIDTH = 2 * WIDTH;
temp3 = 199%BUFFERWIDTH;

现在可以正确解释,因为编译器而不是预处理器可以理解常量。

更一般地说,我强烈敦促您不要使用#define来定义常量。 #define本质上是源代码上的搜索和替换机制,对其替换的内容没有语义或语法理解。它不适合运算符优先级,所以你很容易遇到像这样的bug。另一方面,const 被编译器理解为定义常量,因此当运算符优先级发挥作用时,将正确计算表达式。

希望这有帮助!

答案 2 :(得分:1)

在最后一种情况下,

temp3 = 199%BUFFERWIDTH;

变为

temp3 = 199%2*WIDTH

temp3 = 199%2*100

所以

temp3 = (199%2) * 100 

表示

temp3 = 100.

重写它:

#define BUFFERWIDTH (2*WIDTH)

答案 3 :(得分:1)

使用MACROS时最常见的陷阱之一是没有意识到MACROS是代码替换单元。所以,你的代码:

#define BUFFERWIDTH 2*WIDTH
// ...
temp3 = 199%BUFFERWIDTH;

预处理后转换为:

temp3 = 199%2*100;

如果您应用运算符优先级,则会得到您显示的数字。

答案 4 :(得分:0)

在上一个示例中,199%BUFFERWIDTH扩展为199 % 2 * 100,评估为100。

答案 5 :(得分:0)

预处理器将其转换为199*2%200

由于*的优先级高于%,因此会将其解析为(199 * 2) % 200

这是非平凡的#DEFINE是邪恶的众多原因之一 在这种特殊情况下,您可以使用括号修复它:

#define BUFFERWIDTH (2*WIDTH)

答案 6 :(得分:0)

你陷入Operator Precedence Macro Trap

temp3 = 199%BUFFERWIDTH;

变为:

temp3 = 199%2*WIDTH;

哪个成为:

temp3 = 199%2*100;

由于%*具有相同的优先级,因此从左到右进行评估,您得到temp3 = 1*100;

答案 7 :(得分:0)

这一行:

temp3 = 199%BUFFERWIDTH;

解析为

temp3 = 199%2*WIDTH;

这不是你想要的。将2*WIDTH括在括号中,得到所需的结果:

#define BUFFERWIDTH (2*WIDTH)

答案 8 :(得分:0)

虽然宏视为邪恶,但有些情况下根本无法避免,并且如果编程很多就会轻松。无论多小,所有宏都应该完全括号:

#define BUFFERWIDTH ( 2 * (WIDTH) )

哪会适应您之后对WIDTH所做的任何更改:

#define WITDH (10+12*55)