首先,定义两个没有括号的常量表达式是我的错:
#define BIG_INTERVAL 60 * 60 * 1000
#define SMALL_INTERVAL 1 * 1000
int i = 1;
if (i >= BIG_INTERVAL / SMALL_INTERVAL - 1)
{
printf("Oops!\n");
}
宏扩展后的if
语句为if(i >= 60 * 60 * 1000 / 1 * 1000 - 1)
。
这不是我的意图。但是如果我写if (i >= 3600000000 - 1)
,我会发现一些奇怪的东西。这是错误的。
60 * 60 * 1000 / 1 * 1000 - 1
是什么类型的? int
?
答案 0 :(得分:69)
int
上的所有运营商都返回int
。是的,60 * 60 * 1000 / 1 * 1000 - 1
是int
。但是3599999999的预期结果对于int
而言太大了,因此表达式实际上计算为-694967297(假设32位int
和2的补码)。
文字3600000000
不会发生这种情况,因为大于INT_MAX
的整数文字属于 可以保存完整值的类型。
答案 1 :(得分:42)
60 * 60 * 1000/1 * 1000 - 1 = 3600000 * 1000 - 1,溢出int类型,因此结果可以是任何东西(在你的情况下它是负数,但不一定是)。
要实现你想要的东西():
#define BIG_INTERVAL (60 * 60 * 1000)
#define SMALL_INTERVAL (1 * 1000)
答案 2 :(得分:12)
这是我的测试结果:
60 * 60 * 1000 / 1 * 1000 will result to -694967296
(60 * 60 * 1000) / (1*1000) will result to 3600
您的操作存在问题,即计算的优先级。
您可能需要考虑查看C ++运算符优先级http://msdn.microsoft.com/en-us/library/126fe14k%28v=vs.80%29.aspx。你会找到结果变成-694967296的原因,我觉得溢出的效果。
答案 3 :(得分:9)
如果使用int为64位的编译器,您会发现表达式的结果为false。如果使用int为32位或16位的编译器,则表达式具有未定义的行为,因为有符号整数的溢出不必包含。可能你的确只是环绕,但它并没有。
3600000000是在编译时可见的常量,因此如果int只有32位,那么编译器必须选择long long(或者只要long为64位)。所以你的另一个表达式用足够的位来计算,以避免溢出,结果是正确的。
答案 4 :(得分:4)
可能是你的字符大小超过了2147m左右的签名,这意味着如果你翻过代表,那就变成了负数。正如其他答案所指出的,当扩展时,除法不做任何事情,因此用括号
包围宏定义答案 5 :(得分:2)
你最有可能超出有符号int的有效值范围--3600000000是一个相当大的数字!
发生这种情况时,该值将成为int数据类型的最小负值。
这将导致您的陈述成立。
答案 6 :(得分:1)
该表达式的每个参数都是一个整数,因此结果将是一个整数。
答案 7 :(得分:1)
我认为你对Macros的运作方式感到困惑。您没有使用这些宏中的值,而是使用方程本身。我认为这是你的困惑所在。我认为您应该在宏中使用括号或不使用宏。
答案 8 :(得分:0)
我没有看到任何人提到的一点是,即使完全括起宏定义并不能完全解决问题。
问题是:
#define BIG_INTERVAL 60 * 60 * 1000
(提问者承认缺少括号是个问题)。但即便如此:
#define BIG_INTERVAL (60 * 60 * 1000)
每个常量(60,60和1000)绝对可以表示为int,但产品是3600000,而语言只保证INT_MAX >= 32767
。
该语言表示大整数常量的大小足以保存其值(例如,100000
可以是int
类型或long int
类型,具体取决于这些类型的范围),但它没有表达式,甚至是常量表达式的规则。
你可以像这样解决这个问题:
#define BIG_INTERVAL (60L * 60L * 1000L)
但即使它不需要,它也会使其成为long
类型。
关于运算符优先级问题,这是我最喜欢的例子:
#include <stdio.h>
#define SIX 1+5
#define NINE 8+1
int main(void)
{
printf("%d * %d = %d\n", SIX, NINE, SIX * NINE);
return 0;
}
输出当然是
6 * 9 = 42
(见道格拉斯亚当斯)。