gcc标准标题中有这么多括号

rob*_*hia 44 c macros gcc

为什么GCC头文件中的常量表达式被括号括起来,像这样?

#define INTMAX_MIN (-9223372036854775807LL)
#define INTMAX_MAX (9223372036854775807LL)
Run Code Online (Sandbox Code Playgroud)

如果我省略括号,这会有什么不同?

#define INTMAX_MIN -9223372036854775807LL
#define INTMAX_MAX 9223372036854775807LL
Run Code Online (Sandbox Code Playgroud)

为什么有'L'后缀?如果我写以下内容会是一样的吗?

#define INTMAX_MIN -9223372036854775807
#define INTMAX_MAX 9223372036854775807
Run Code Online (Sandbox Code Playgroud)

是否有实际用途或者总是相同的东西?

我知道'L'代表很长时间,我也很清楚C宏中括号的重要性; 我是为了好奇而问这个.

小智 84

如果你写的

a = 7 INTMAX_MIN;
Run Code Online (Sandbox Code Playgroud)

你会期望得到一个语法错误,因为从表面上看这将是一个非法表达.它会,因为它扩展到

a = 7 (-9223372036854775807LL);
Run Code Online (Sandbox Code Playgroud)

这确实给你一个语法错误.但如果没有括号,它将扩展为:

a = 7 -9223372036854775807LL;
Run Code Online (Sandbox Code Playgroud)

虽然显然不是你想要的,但它不会给你一个错误.

更一般地说,所有这些定义都为扩展看起来像标识符的东西提供了扩展.在算术表达式中,标识符是"主表达式",但不是-9223372036854775807LL.但是,带括号的表达式是"主要表达式".

这才是真正的原因.从而使宏展开是什么样子的主要表达的东西,一个主要的表达.你永远不会对发生的事情感到惊讶.在编程中,惊喜通常很糟糕.

通常没关系,但编写定义的人不希望它们通常起作用.他们希望他们永远工作.

尾随LL将此整数文字标记为类型long long,通常(在本例中为64位).如果没有LL后缀,则可以将文字解释为int,long int或long long int,以第一个支持64位值为准.确定类型可能与确定价值一样重要.

  • 您可能还会讨论`a = 7-INT_MAX;`在`INT_MAX`周围有和没有括号,注意结果与`a = 7 - INT_MAX;`不同. (10认同)
  • @EricMSchmidt:_ ...等等......等等......除非......**哦,drat!最初的单独预处理器过程倾向于给出一个答案,但是现代(如1989或更高版本)版本标记化输入并且输入保持标记化,因此`#define X -7`和`int main(void){int x = 7-X; 返回x; 产生一个以状态14退出的程序.我应该记住. (3认同)

oua*_*uah 19

将括号放在带有整数常量的宏和一元运算符上是一个很好的做法,如下所示:

#define BLA (-1)
Run Code Online (Sandbox Code Playgroud)

由于一元运算符(-此处)在C中没有最高优先级.后缀运算符的优先级高于一元运算符.请记住,C没有负常数,例如,-1是一-元运算符之前的常量表达式.

另外PC-Lint建议在这些宏中使用括号:

(规则973):parentheser #define N(-1)宏'符号'中的一元运算符没有括号 - 发现在类似表达式的宏中出现的一元运算符没有括号.例如:

#define N -1
Run Code Online (Sandbox Code Playgroud)

用户可能更喜欢将以下内容括起来:

#define N (-1)
Run Code Online (Sandbox Code Playgroud)


chu*_*ica 13

这个答案试图说明为什么LL需要它.(这并不容易.)
其他答案已经说明了为什么需要括号.

让我们编写三个宏,都是十进制常量.

#define MAXILL (9223372036854775807LL)
#define MAXIL  (9223372036854775807L)
#define MAXI   (9223372036854775807)
Run Code Online (Sandbox Code Playgroud)

即使MAXI没有后缀,也不会使其成为类型int.MAXI将具有第一种类型的它适合,无论是int,long,long long或扩展的整数类型.

即使MAXILL后缀,它也会有第一种类型long,long long或者是扩展的整数类型.

即使MAXILLLL后缀,它也会有第一种类型,long long或者是扩展的整数类型.

在每种情况下,宏都具有相同的值,但可能具有不同的类型.

有关类型确定,请参见C11dr§6.4.4.1.5.


让我们试着将它们打印,并具有intlong是32位和long longintmax_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
Run Code Online (Sandbox Code Playgroud)

最后一行中的所有三个都是正确的,因为所有三个宏都是正确的long long,前面的格式说明符和数字之间的类型不匹配.

如果我们有int32位long,long long并且intmax_t是64,那么以下是正确的.

printf("LI  %ld %ld",    MAXI, MAXIL);
printf("LLI %lld", MAXILL);
Run Code Online (Sandbox Code Playgroud)

最大宽度整数类型的格式说明符为"%" PRIdMAX.此宏无法扩展"%ld" "%lld"容纳MAXI, MAXIL, MAXILL.它被设置为"%lld"intmax_t需要具有相同类型相关的数字.在这种情况下,long longMAXILL应使用表格.


其他实现可以具有扩展的整数类型(例如int128_t),在这种情况下,可以使用实现特定的后缀或某种机制.