Jan*_*tke 9 c c-preprocessor c23
在C23中,nullptr关键字得到了标准化。我也更愿意使用C23 之前nullptr的版本NULL,因为这意味着我可以编写可编译的代码:
我可以简单地NULL在两种语言和每个 C 标准中使用,但这在 C++ 代码中是非常不寻常的,并且nullptr无论如何正在成为两种语言的规范。
#define据我所知,语言中不允许使用替换关键字,这可能会在定义兼容性宏时引起问题。基本上,我需要:
// only if this is neither C++ nor C23
#define nullptr /* something */
Run Code Online (Sandbox Code Playgroud)
我怎样才能正确定义这个宏?
Lun*_*din 12
一些注意事项:
__STDC__并__STDC_VERSION__添加到“C95”(ISO C 9899:1990 的附录)中。nullptr使用预处理器条件,因为它不是宏。stddef.h或等效标头,因此不要假设该标头是#included。-std=c2x确实包含nullptr但设置__STDC_VERSION__为占位符值 202000L。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
#define nullptr (void*)0
typedef void* nullptr_t;
#endif
Run Code Online (Sandbox Code Playgroud)
可以通过预定义宏检测您是否正在使用 C23 :
/* bad, don't do this */
#if !__cplusplus && __STDC_VERSION__ <= 201710
#define nullptr ((void*)0)
#endif
Run Code Online (Sandbox Code Playgroud)
然而,这样一个简单的宏可能会触发编译器警告(clang -Wundef -std=c89):
<source>:1:6: warning: '__cplusplus' is not defined, evaluates to 0 [-Wundef]
1 | #if !__cplusplus && __STDC_VERSION__ <= 201710
| ^
<source>:1:21: warning: '__STDC_VERSION__' is not defined, evaluates to 0 [-Wundef]
1 | #if !__cplusplus && __STDC_VERSION__ <= 201710
|
Run Code Online (Sandbox Code Playgroud)
可以重写该解决方案,这样就不会触发警告:
/* don't do anything in C++, or if someone else defined a compatibility macro */
#if !defined(__cplusplus) && !defined(nullptr) && \
(!defined(__STDC_VERSION__) || __STDC_VERSION__ <= 201710)
/* -Wundef is avoided by using short circuiting in the condition */
#define nullptr ((void*)0)
#endif
Run Code Online (Sandbox Code Playgroud)