我有一个在C和C之间共享的头文件,里面有一些C特定的代码。所以我在里面使用#ifdef __cplusplus
。
然而,我有一个用整数字面量和单引号作为分隔符定义的值:int a = 0B0000'0001;
,看起来预处理器不喜欢它。
它可以在visual studio上正常工作,但在Linux上不行,gcc和unifdef都可以(这帮助我理解了错误)
#ifdef __cplusplus
int a = 0B0000'0001;
#endif
字符串
这段简单的代码会破坏C代码。
简单的解决办法是去掉单引号。但是如果有其他的解决办法,
编辑:重复有点回答这个问题,但它是不一样的,因为我实际上不需要使用C中的数字分隔符(但预处理器)
所以,总结一下:
- 如果你有gcc >=12:使用flag -std= c2 x
- 如果没有,可以使用变通方法:
// workaround: final quote for pre-c2x: '
on the same line
1条答案
按热度按时间cxfofazt1#
C14是第一个使用
'
来分隔数字组的标准。C不能使用_
而不是'
是有技术原因的。C14还添加了二进制常量,前缀为0b
或0B
。C23将添加数字标点和二进制常量特性,这使它与C保持一致,但数字标点使C代码的专门解析比以前困难得多。
这意味着您可以使用能够识别
-std=c2x
(或者-std=c23
或-std=c24
-我不确定他们会决定哪一个)的GCC版本编译代码。你不能用只识别C18(或者C17?)或更早标准的C编译器编译代码,因为输入是由C预处理器标记的。
C11标准§6.10.1条件包含¶6规定:
每个指令的条件都是按顺序检查的。如果它的计算结果为false(零),它所控制的组将被跳过:指令只通过确定指令的名称进行处理,以跟踪嵌套条件的级别;忽略指令的其余预处理令牌,组中的其他预处理标记也是如此。仅处理控制条件计算结果为true(非零)的第一个组。如果没有条件计算结果为true,并且存在
#else
指令,则处理由#else
控制的组;缺少#else
指令,则跳过直到#endif
的所有组。问题是它工作在“预处理token”上,在C23之前,
0B0000'0001
中的'
开始了一个字符常量token,但没有匹配的关闭引号,因此token无效/不完整。有几个可能的但讨厌的、黑客式的变通方法。Jarod42在评论中建议的一个是:
添加
// workaround: final quote for pre-c2x: '
可能是一种解决方法。类似地,你可以确保所有带标点的数字都包含偶数个单引号。例如,在八进制数字组中给二进制数字加标点也可以:
0B00'000'001
。始终使用偶数个标点字符!Arteyr建议:
你也可以把C++的东西放在一个不同的文件中,
字符串
所以C预处理器甚至不会打开包含
0B0000'0001
的文件。请注意,用二进制表示64位的数字是不明智的,即使使用标点符号也是如此。
型
这在十六进制中会更合理,但是在四个四进制数之间会有三个分隔符,这仍然会给C18或更早版本和C++11或更早版本的编译器带来麻烦:
型
我的建议是:
(顺便说一句,C++原始字符串字面量对于专门的代码解析器来说更是噩梦。幸运的是,原始字符串字面量不是C23的一部分。)