为什么GCC头文件中的常量表达式被括号括起来,比如这个?
#define INTMAX_MIN (-9223372036854775807LL)
#define INTMAX_MAX (9223372036854775807LL)
如果我省略括号,这会有什么不同?
#define INTMAX_MIN -9223372036854775807LL
#define INTMAX_MAX 9223372036854775807LL
为什么有'L'后缀?如果我写以下内容会不会一样?
#define INTMAX_MIN -9223372036854775807
#define INTMAX_MAX 9223372036854775807
是否有实际用途或是否始终相同?
我知道'L'代表很长时间,我也很清楚C宏中括号的重要性;我是为了好奇而问这个。
答案 0 :(得分:84)
如果你写了
a = 7 INTMAX_MIN;
你会期望得到一个语法错误,因为从表面上看这将是一个非法表达。它会,因为它扩展到
a = 7 (-9223372036854775807LL);
确实会给你一个语法错误。但如果没有括号,它将扩展为:
a = 7 -9223372036854775807LL;
虽然显然不是你想要的,但它不会给你一个错误。
更一般地说,所有这些定义都会为看起来像标识符的东西进行扩展。在算术表达式中,标识符是“主表达式”,但不是-9223372036854775807LL。但是,带括号的表达式是“主要表达式”。
这才是真正的原因。这样宏就可以将看起来像的主表达式扩展为 主表达式的东西。你永远不会对发生的事情感到惊讶。在编程中,惊喜通常很糟糕。
通常没关系,但编写定义的人不希望它们通常起作用。他们希望他们一直工作。
尾随LL标记此类型为long long
的整数文字,通常(在本例中为64位)。如果没有LL后缀,则可以将文字解释为int,long int或long long int,以第一个支持64位值为准。确定类型可能与确定价值一样重要。
答案 1 :(得分:19)
将括号放在带有整数常量的宏和这样的一元运算符上是一个很好的做法:
#define BLA (-1)
因为一元运算符(此处-
)在C中没有最高优先级。后缀运算符的优先级高于一元运算符。请记住,C没有负常数,例如-1
是一个以-
一元运算符开头的常量表达式。
另外PC-Lint建议在这些宏中使用括号:
(规则973):括号#define N(-1) 宏'符号'中的一元运算符没有括号 - 一元 出现在类似表达式的宏中的运算符被发现没有括号。对于 例如:
#define N -1
用户可能更喜欢将以下内容括起来:
#define N (-1)
答案 2 :(得分:13)
此答案试图说明为什么需要LL
。 (这并不容易。)
其他答案显示了为什么需要括号。
让我们编写三个宏,所有都是十进制常量。
#define MAXILL (9223372036854775807LL)
#define MAXIL (9223372036854775807L)
#define MAXI (9223372036854775807)
即使MAXI
没有后缀,也不会使其键入int
。 MAXI
将具有适合的第一种类型,int
,long
,long long
或扩展整数类型。
即使MAXIL
具有L
后缀,它也会有第一种类型,long
,long long
或扩展整数类型。
即使MAXILL
具有LL
后缀,它也会有第一种类型,long long
或扩展整数类型。
在每种情况下,宏都具有相同的值,但可能不同的类型。
参见C11dr§6.4.4.15进行类型确定。
让我们尝试打印它们,int
和long
为32位,long long
和intmax_t
为64。
printf("I %d %d %d", MAXI, MAXIL, MAXILL); //Error: type mismatch
printf("LI %ld %ld %ld", MAXI, MAXIL, MAXILL); //Error: type mismatch
printf("LLI %lld %lld %lld", MAXI, MAXIL, MAXILL); //Ok
最后一行中的所有三个都是正确的,因为所有三个宏都是long long
,前面的格式说明符和数字之间的类型不匹配。
如果我们int
是32位且long
,long long
和intmax_t
是64,那么以下内容是正确的。
printf("LI %ld %ld", MAXI, MAXIL);
printf("LLI %lld", MAXILL);
最大宽度整数类型的格式说明符为"%" PRIdMAX
。此宏无法展开到"%ld"
和 "%lld"
以容纳MAXI, MAXIL, MAXILL
。它设置为"%lld"
,与intmax_t
相关的数字需要具有相同的类型。在这种情况下,应使用long long
并且只能使用MAXILL
形式。
其他实现可以有一个扩展的整数类型(如int128_t
),在这种情况下可以使用特定于实现的后缀或某种机制。