c - 在 C 中构建时断言表达式的方法

标签 c refactoring assert static-assert

我正在整理一些旧代码,这些代码到处都使用“魔数(Magic Number)”来设置硬件寄存器,我想使用常量而不是这些数字来使代码更具表现力(事实上它们会映射到用于记录寄存器的名称/值)。

但是,我担心随着更改量的增加,我可能会打破神奇的数字。下面是一个简化的例子(寄存器组比较复杂):

const short mode0 = 0;
const short mode1 = 1;
const short mode2 = 2;

const short state0 = 0;
const short state1 = 4;
const short state2 = 8;

所以代替:

set_register(5);

我们有:

set_register(state1|mode1);

我正在寻找的是以下的构建时版本:

ASSERT(5==(state1|mode1));

更新

@Christian,感谢您的快速回复,我也对 C/非增强环境的答案感兴趣,因为这是驱动程序/内核代码。

最佳答案

新答案:

在我最初的回答(如下)中,我必须有两个不同的宏来支持函数范围和全局范围内的断言。我想知道是否有可能提出一个适用于两个范围的单一解决方案。

我能够使用外部字符数组找到适用于 Visual Studio 和 Comeau 编译器的解决方案。但我能够找到适用于 GCC 的更复杂的解决方案。但是 GCC 的解决方案不适用于 Visual Studio。 :( 但添加“#ifdef __ GNUC __”后,很容易为给定的编译器选择正确的宏集。

解决方案:

#ifdef __GNUC__
#define STATIC_ASSERT_HELPER(expr, msg) \
    (!!sizeof \ (struct { unsigned int STATIC_ASSERTION__##msg: (expr) ? 1 : -1; }))
#define STATIC_ASSERT(expr, msg) \
    extern int (*assert_function__(void)) [STATIC_ASSERT_HELPER(expr, msg)]
#else
    #define STATIC_ASSERT(expr, msg)   \
    extern char STATIC_ASSERTION__##msg[1]; \
    extern char STATIC_ASSERTION__##msg[(expr)?1:2]
#endif /* #ifdef __GNUC__ */

以下是 test.c 第 22 行为 STATIC_ASSERT(1==1, test_message); 报告的错误消息:

海湾合作委员会:

line 22: error: negative width in bit-field `STATIC_ASSERTION__test_message'

Visual Studio :

test.c(22) : error C2369: 'STATIC_ASSERTION__test_message' : redefinition; different subscripts
    test.c(22) : see declaration of 'STATIC_ASSERTION__test_message'

科莫:

line 22: error: declaration is incompatible with
        "char STATIC_ASSERTION__test_message[1]" (declared at line 22)



原始答案:

我做的事情与跳棋所做的非常相似。但我包含一条会在许多编译器中显示的消息:

#define STATIC_ASSERT(expr, msg)               \
{                                              \
    char STATIC_ASSERTION__##msg[(expr)?1:-1]; \
    (void)STATIC_ASSERTION__##msg[0];          \
}

要在全局范围内(在函数之外)做一些事情,请使用:

#define GLOBAL_STATIC_ASSERT(expr, msg)   \
  extern char STATIC_ASSERTION__##msg[1]; \
  extern char STATIC_ASSERTION__##msg[(expr)?1:2]

关于c - 在 C 中构建时断言表达式的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/174356/

相关文章:

c - 为什么我从函数调用中获得垃圾值?

c++ - 一行中的 Assert::AreEqual 格式消息

c - 如何在 C 中访问数组中的特定结构?

c - UNIX下如何使用(C)将文件从一个文件夹传输到另一个文件夹?

c - 在 C 中将目录构建为树

iphone - 闯入 iPhone 上的调试器

c# - .Net 4.5.2 中 Debug.Assert(condition, interpolatedStringMessage) 的求值顺序

perl - 是否可以在不执行其语句的情况下使用或要求 Perl 脚本?

java - 将类似方法重构为策略模式的性能成本?

java - 使用 Groovy 和 Java 改进代码的最佳方法、技巧和示例