gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 02:47:30 26 4
gpt4 key购买 nike

似乎预处理器在连接有符号数字的 token 时添加了一个空格。
我试过这个:

#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,
};

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

最佳答案

简短的版本是 +12不是预处理器 token ,也不是 -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 .
注意这里1 , 1e+ , 1e+12 , 和 1e+12f都是 pp 编号,但 +12-12不是。这就是在咬你。

根据预处理器规则,替换列表中的参数被参数标记序列替换;然后,每个 ##被申请;被应用。应用程序删除 ##并将前面的标记连接到后面的标记。如果该组合不是有效的预处理器 token ,则结果未定义。 (作为引用,预处理器标记可以是标题名称、标识符、pp 编号、字符常量、字符串文字、标点符号或不属于其中之一的非空白字符;仅此而已)。

当应用 1e##IE##f 且 IE 为 +12 时,您实际上是在做 < 1e >##< + >< 12 >##< f >,使用尖括号表示单个标记。无论顺序如何(这很好,因为 ## 顺序未指定),两种粘贴都会产生有效的 pp-numbers < 1e+ > 和 < 12f >.但结果给您留下 < 1e+ >< 12f > 而不是想要的 < 1e+12f >.

How can I avoid it?


不幸的是你不得不放弃路过 +12-12标记序列作为参数。您可以接受 +, 12作为两个参数,但是在将它们分步组合时需要小心,因为 ## 的顺序运算符未指定和 +12不是有效的预处理器 token (否则它可能会起作用,但不允许......这种情况可能是一个噩梦般的定时炸弹):
#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),
};

...或者您可以简单地使用特定于符号的宏;并且严格自 1e12f1e+12f是相同的值(除非他们只是运行预处理器,否则没人会看到它),你只能使用两个宏:
#define DECL_FL(IE) 1e##IE##f
#define DECL_FL_E_NEG(IE) 1e-##IE##f
float val[] =
{
DECL_FL(12),
DECL_FL_E_NEG(12),
DECL_FL(12),
};

关于concatenation - c 预处理器在将数字与符号连接时添加一个空格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53803996/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com