“解决方案”;“全局范围中的分号”;无op C宏的警告 在一个可以作为C或C++构建的代码库中,我认为我会利用一个宏来利用 StistaSytRe>/Cuff>,它是以C++ 11或更高的方式构建的。
(注意:我知道,至少如果你愿意接受一个message参数——尽管它不会在任何地方都有效。但是为了便于讨论,让我们假设我有一些正当的需要使它不接受任何消息,并且至少在一些C构建中是不可操作的。) 下面是我尝试过的简单定义:“解决方案”;“全局范围中的分号”;无op C宏的警告 在一个可以作为C或C++构建的代码库中,我认为我会利用一个宏来利用 StistaSytRe>/Cuff>,它是以C++ 11或更高的方式构建的。,c,c89,static-assert,C,C89,Static Assert,(注意:我知道,至少如果你愿意接受一个message参数——尽管它不会在任何地方都有效。但是为了便于讨论,让我们假设我有一些正当的需要使它不接受任何消息,并且至少在一些C构建中是不可操作的。) 下面是我尝试过的简单定义: #if defined(__cplusplus) && __cplusplus >= 201103L #define STATIC_ASSERT(cond) \ static_assert((cond), #cond) #else
#if defined(__cplusplus) && __cplusplus >= 201103L
#define STATIC_ASSERT(cond) \
static_assert((cond), #cond)
#else
#define STATIC_ASSERT(cond)
#endif
宏中没有分号,目的是将其添加到调用站点。但在pedantic C警告设置下,此宏出现在全局范围内会导致:
错误:ISO C不允许额外的“;”在函数之外[-Werror=pedantic]
简单的解决方案似乎是从调用站点中去掉分号,并将其放在宏的C++11端。但我想知道:如何在全局范围内创建一个no-op宏,允许在调用站点使用分号(而不会与其他警告冲突)?由于结构的正向声明可能会重复很多次,因此可以使用伪声明:
#define STATIC_ASSERT(cond) struct GlobalScopeNoopTrick
@JonathanLeffler说,这应该适用于较旧的编译器,即使是C11之前的编译器……但是:
“如果您有一个C90编译器,如果在中的语句后有一个静态断言,它会反对。这不是您主要关心的问题(如果静态断言也可以,则在文件范围内总是可以),但它不限于在文件范围内使用。尽管风险很低”
对于编译时可能不完全没有操作的相关情况,C11引入了重复typedef的功能。正如在节目之前关于C中静态断言的文章中所链接的那样,有一些方法可以使用行号或其他消歧器绕过旧C的typedef复制:
/* Standard indirection to allow concatenation after expansion */
#define CONCAT(a,b) CONCAT_(a,b)
#define CONCAT_(a,b) a##b
#if defined(__cplusplus) && __cplusplus >= 201103L
#define STATIC_ASSERT(cond) \
static_assert((cond), #cond)
#else
#define STATIC_ASSERT(cond) typedef void CONCAT(dummy_unused_,__LINE__)
#endif
只要静态断言每行出现一个,标识符就不会相互冲突。不需要
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。类型定义可能会重复,因此任何不使用的名称都可以;可以使用typedef void VoidTypeKludge
。也可以使用struct staticassertsubrogate
作为替换文本,这将适用于C11以前的编译器(此时可以重复typedef)。结构标记是否作为真正的结构类型存在并不重要。@JonathanLeffler-谢谢,我只是在检查C89.C11中的typedef重新定义规则。关于typedef名称的措辞可能会被重新定义,以表示与当前相同的类型是新的。@HostileFork-我在中编辑替代名称后不久退出。我把它标记为CW(在手机上唯一相对容易的东西)。如果你不介意的话,进行编辑。或者我以后再谈。#定义静态断言(cond)void never_called()
--分号完成正向声明。@RaymondChen在某些编译器/警告组合中,似乎会多次收到关于正向函数声明的警告。您可以禁用它们,但假设它们存在是有充分理由的……下面的结构解决方案似乎不会触发任何警告。