在C23中,nullptr keyword得到了标准化.我更喜欢使用nullptr,而不是C23之前的NULL,因为这意味着我可以编写在以下代码中编译的代码:

  • C、C23之前
  • C,自C23起
  • C++

我可以简单地在两种语言和每种C标准中使用NULL,但在C++代码中这将是非常不寻常的,而且nullptr正在成为两种语言的标准.

据我所知,不允许使用#define来替换语言中的关键字,这可能会在定义兼容宏时造成问题.基本上,我需要:

// only if this is neither C++ nor C23
#define nullptr /* something */

如何正确定义此宏?

推荐答案

以下是一些值得注意的事情:

  • 在"C95"(ISO C 9899:1990的增编)中增加了__STDC____STDC_VERSION__.
  • 您不能使用预处理器条件判断nullptr,因为它不是宏.
  • 即使在使用符合要求的C23编译器时,用户也可能忘记包含stddef.h或等效头文件,所以不要假设这个是#Included.
  • 当前版本的GCC和clang支持-std=c2x,其中包含nullptr,但将__STDC_VERSION__设置为占位符值202000L.
  • 并非所有版本的C++都包含nullptr,因为它是在C++11中添加的.

因此,宏判断应如下所示:

/* C++11 or later? */
#if (defined(__cplusplus) && __cplusplus >= 201103L)  
  #include <cstddef>

/* C2x/C23 or later? */
#elif ( defined(__STDC__) &&          \
        defined(__STDC_VERSION__) &&  \
        (__STDC_VERSION__ >= 202000L) )
  #include <stddef.h> /* nullptr_t */

/* pre C23, pre C++11 or non-standard */
#else
  #include <stddef.h> /* NULL */
  #define nullptr NULL
  typedef void* nullptr_t;

#endif

C++相关问答推荐

为什么在Linux(特别是Ubuntu 20.04LTS)上,POSIX共享内存对象在重启后仍然存在,然后突然变成了根用户?

显式地将值转换为它从函数返回的类型的含义是什么?

SDL 2.0-从数组渲染纹理

为什么C语言允许你使用var =(struct NAME){

不会停在空格或换行符上的错误

我在这里正确地解释了C操作顺序吗?

在C语言中,是否可以使枚举数向后计数?

GCC奇怪的行为,有fork 和印花,有换行符和不换行符

我在C程序的Flex/Bison中遇到语法错误

Valgrind用net_pton()抱怨

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

隐藏测试用例无法在c程序中计算位数.

在吉陀罗中,_2_1_和CONCAT11是什么意思?

C23标准是否向后兼容?

`%%的sscanf无法按预期工作

";错误:寄存器的使用无效;当使用-masm=intel;在gcc中,但在AT&;T模式

将数组返回到链表

C 中 struct 体自赋值是否安全?特别是如果一侧是指向 struct 的指针?

`void foo(int a[static 0]);` 有效吗?

c 函数指针,另一种语法