ifdef __cplusplus中的整数文字单引号

v9tzhpje  于 9个月前  发布在  其他
关注(0)|答案(1)|浏览(91)

我有一个在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
cxfofazt

cxfofazt1#

  • 将评论转化为回答,并扩展讨论。

C14是第一个使用'来分隔数字组的标准。C不能使用_而不是'是有技术原因的。C14还添加了二进制常量,前缀为0b0B
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++的东西放在一个不同的文件中,

#ifdef __cplusplus
#include "./cpp_header.hpp"
#endif

字符串
所以C预处理器甚至不会打开包含0B0000'0001的文件。
请注意,用二进制表示64位的数字是不明智的,即使使用标点符号也是如此。

0B10100000'00000100'00000000'00000010'00000000'00101010'00000000'00111000


这在十六进制中会更合理,但是在四个四进制数之间会有三个分隔符,这仍然会给C18或更早版本和C++11或更早版本的编译器带来麻烦:

0xA004'0002'002A'0038


我的建议是:

  • 不要使用数字标点符号,直到你需要使用的所有C和C++编译器都支持它。
  • 不要使用二进制来表示64位值,而要使用十六进制。

(顺便说一句,C++原始字符串字面量对于专门的代码解析器来说更是噩梦。幸运的是,原始字符串字面量不是C23的一部分。)

相关问题