我有一个在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=c2x
  • 如果没有,您可以使用一个变通方法:在同一行上有// workaround: final quote for pre-c2x: '

推荐答案

Transferring commentary into an answer and expanding on the discussion.

C++14是第一个包含数字标点符号的标准,使用'来分隔数字组.C++不能使用_而不是'是有技术原因的.C++14还添加了前缀为0b0B的二进制常量.

C23将增加数字标点符号和二进制常量功能.这使它与C++保持一致,但数字标点符号使得C代码的临时解析比以前困难得多.

这意味着你可以用GCC的一个版本来编译代码,这个版本可以识别-std=c2x(或者-std=c23或者-std=c24--我不确定他们会 Select 哪一个).

不能用只识别C18(或者是C17?)或更早的标准的C编译器编译代码.这是因为输入是由C预处理器标记的.

C11标准§6.10.1 Conditional inclusion ¶6规定:

每个指令的条件都按顺序判断.如果它的计算结果为false(零),则跳过它所控制的组:指令只通过确定指令的名称进行处理,以跟踪嵌套条件的级别;其余指令的预处理标记被忽略,组中的其他预处理标记也被忽略.仅处理控制条件计算结果为true(非零)的第一个组.如果没有一个条件计算为true,并且有一个#else指令,则处理由#else控制的组;如果没有#else指令,则跳过#endif之前的所有组.

问题是,它是在"预处理令牌"上工作的,在C23之前,0B0000'0001中的'开始一个字符常量令牌,但没有匹配的右引号,所以令牌无效/不完整.

有一些可能的、但令人讨厌的、老套的解决办法.其中一个是comment分中Jarod42分建议的:

添加// workaround: final quote for pre-c2x: '可能是一种变通办法.

同样,您可以确保所有带标点符号的数字都包含偶数个单引号.例如,以八进制数字分组对二进制进行标点也可以:0B00'000'001.始终使用偶数个标点符号字符!

Arteyr suggested:

您还可以将C++程序放在不同的文件中,并拥有

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

所以C预处理器甚至不会打开包含0B0000'0001个字符的文件.

请注意,用二进制表示64位数字是不明智的,即使使用标点符号也是如此.如果你用八位字节来标点,那么也会有7个标点符号!

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

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

0xA004'0002'002A'0038

我的建议是:

  • 在您需要使用的所有C和C++编译器都支持数字标点符号之前,不要使用它.
  • 不要使用二进制来表示64位值.改用十六进制.

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

C++相关问答推荐

是否有任何情况(特定类型/值),类型双关在所有符合标准的C实现中产生相同的行为?

字符串令牌化xpath表达式

GCC预处理宏和#杂注GCC展开

C中函数类型的前向声明

如何将常量char*复制到char数组

如何使用C for Linux和Windows的标准输入与gdb/mi进行通信?

如何使用[BTStack]BLE发送大型(>;2kb)信息包

为什么将函数名括在括号中会禁用隐式声明?

在Linux上使用vscode和lldb调试用Makefile编译的c代码

从TCP连接启动UDP(C套接字)

Caesar密码调试:输出文本末尾的问号和随机字符

我应该在递归中使用全局变量吗

链接器脚本和C程序使用相同的头文件,这可能吗?

如何修复我的qsort()算法?它每次都给出不同的结果

Dlsym()的手册页解决方法仍然容易出错?

共享内存未授予父进程权限

将char*铸造为空**

快速准确计算double的小数指数

为什么使用 C 引用这个 char 数组会导致 Stack smasing?

窗口消息处理函数以某种方式更改了应保持不变的 int 变量的值