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 ......
只是想知道造成这种情况的原因:)
答案 0 :(得分:8)
答案 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)