如何在 _Static_assert 中使用 const int?

How to use const int in _Static_assert?

前言:我想在C程序中静态检查结构成员的数量,所以我创建了两个宏,每个宏都创建常量int,将__LINE__存储到变量中:

 #include <stdio.h>
 #include <string.h>
 #define BEGIN(log) const int __##log##_begin = __LINE__;
 #define END(log) const int __##log##_end = __LINE__;
 BEGIN(TEST);
 struct TEST {
    int t1;
    int t2;
    float t3;
    int t4;
    int t5;
    int t6;
 };
 END(TEST)

 main()
 {
    static_assert(__TEST_end - __TEST_begin  == 6 + 3, "not_equal");
 }

当我使用带有 -std=c++11 选项的 C++ 编译器时 (c++ test.cpp -std=c++11),它工作正常,但相同的代码(替换 static_assert 到 _Static_assert) 在 C(gcc 版本 4.8.4)中不起作用并出现奇怪的错误,因为可以在编译时评估此表达式:

test.c: In function ‘main’: test.c:18:17: error: expression in static assertion is not constant _Static_assert(__TEST_end - __TEST_begin == 6 + 4, "not_equal");

如何修复此错误或在 C 中实现最初的目标?

在 C 中,即使使用 const 定义的变量也不是常量表达式。 _Static_assert 要求它的第一个参数是常量表达式。因此,在 C++ 中可以完成的事情不能在 C 中完成。

您可以改为执行运行时检查;使用断言。

请注意,此方法不会防止程序员在同一行中键入两个成员或使用同一类型的多个单行声明,或添加空行(或注释)。与其强迫程序员遵循字符串编码模式,只是为了让这个断言能够捕获错误,不如简单地要求程序员定义正确数量的成员,这样就不太容易出错。绝对更好,因为无论哪种方式都可以使错误检测不到,但至少不必担心严格的编码模式。

您的问题的解决方案是使用匿名枚举。而不是:

#define BEGIN(log) const int __##log##_begin = __LINE__
#define END(log) const int __##log##_end = __LINE__

做:

#define BEGIN(log) enum { __##log##_begin = __LINE__ }
#define END(log) enum { __##log##_end = __LINE__ }

这在 C11 中是允许的,因为与 const int(甚至 static const int)变量不同,枚举常量 定义为整数常量表达式。

(顺便说一句,我从我的 BEGIN()/END() 宏版本中省略了终端分号。在我看来,声明宏不应包含终端分号,应该提供由宏用户,所以宏的行为更像一个 non-macro C 声明。)