c将数字与符号连接时,预处理器添加一个空格

时间:2018-12-16 16:08:39

标签: concatenation c-preprocessor

在连接带符号数字的令牌时,预处理器似乎增加了一个空格。 我尝试过:

#define DECL_FL(IE) 1e##IE##f

float val[] = 
{
    DECL_FL(12),
    DECL_FL(-12),
    DECL_FL(+12),
};

我运行预处理器:

$ gcc test.c -E
# 1 "test.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "test.c"

float val[] =
{
 1e12f,
 1e- 12f,
 1e+ 12f,
};

数组中的第一个元素正确。对于其他两个元素,在数字和符号之间添加一个空格。
为什么预处理器要添加空间?我该如何避免呢?

2 个答案:

答案 0 :(得分:2)

简短的版本是+12不是预处理器令牌,-12也不是;而是每个都是两个预处理器令牌(即+-是标点符号; 12分别是pp数)。

我们实际上是在处理pp-number,因此这是pp-number的语法规则:

pp-number: digit . digit pp-number digit pp-number identifier-nondigit pp-number e sign pp-number E sign pp-number p sign pp-number P sign pp-number . 请注意,11e+1e+121e+12f都是pp编号,而+12-12不是pp编号。这是在咬你。

根据预处理程序规则,替换列表中的参数由参数令牌序列替换;然后,将应用每个##。该应用程序删除##并将前面的令牌连接到后面的令牌。如果该组合不是有效的预处理器令牌,则结果不确定。 (作为参考,预处理器令牌可以是标头名称,标识符,pp-number,字符常量,字符串文字,标点符号或不属于这些字符的非空白字符;仅此而已。)

在IE为+12的情况下应用1e ## IE ## f时,实际上是在做<1e> ## <{+> <12> ## <{ {1}}>,使用尖括号表示各个标记。两种粘贴方式,无论顺序如何(这都很好,因为未指定##顺序),都将生成有效的pp号<f>和<1e+>。但是结果使您只能使用<12f> <1e+>而不是所需的<12f>。

如何避免呢?

不幸的是,您必须放弃传递1e+12f+12令牌序列作为参数。您可以接受-12作为两个参数,但是在逐步组合它们时要小心,因为+, 12运算符的顺序未指定,并且##不是有效的预处理器令牌(否则它可能有效,但不允许...并且 情况可能是噩梦般的定时炸弹):

+12

...或者您可以简单地使用符号专用宏;严格来说,由于#define PASTE(A,B) A##B #define DECL_FL(IE) 1e##IE##f #define DECL_FL_SGN(S,IE) PASTE(1e##S,IE##f) float val[] = { DECL_FL(12), DECL_FL_SGN(+,12), DECL_FL_SGN(-,12), }; 1e12f是相同的值(除非他们只运行预处理程序,否则任何人都不会看到它),您只能使用两个宏:

1e+12f

答案 1 :(得分:-1)

##是令牌粘贴运算符,如果使用后未形成有效令牌,则此方法将无效,因为C 1e+12f不是有效的预处理令牌,因此它正在尝试插入空间或可能导致意外的行为,您可以在以下文档中找到它。

http://gcc.gnu.org/onlinedocs/cpp/Concatenation.html