如何在构建时用C断言前pressions [英] Ways to ASSERT expressions at build time in C
问题描述
我整理使用一些旧的code幻数各地设置硬件寄存器,我想使用常量,而不是这些数字,使code稍微更前的地方pressive(事实上,他们将映射到用于记录注册的名称/值)。
I'm tidying up some older code that uses 'magic numbers' all over the place to set hardware registers, and I would like to use constants instead of these numbers to make the code somewhat more expressive (in fact they will map to the names/values used to document the registers).
不过,我担心有改动的量我可能打破幻数。下面是一个简化的例子(寄存器集是更复杂的):
However, I'm concerned that with the volume of changes I might break the magic numbers. Here is a simplified example (the register set is more complex):
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 /非增压的环境太回答,因为这是驱动/内核code。
@Christian, thanks for the quick response, I'm interested on a C / non-boost environment answer too because this is driver/kernel code.
推荐答案
新的答案
在我原来的答复(见下文),我必须有两个不同的宏来支持一个函数范围,并在全球范围内的断言。我在想,如果有可能拿出一个解决方案,将在这两个领域的工作。
In my original answer (below), I had to have two different macros to support assertions in a function scope and at the global scope. I wondered if it was possible to come up with a single solution that would work in both scopes.
我能找到工作了Visual Studio和科莫使用EXTERN的字符数组的编译器的解决方案。但我能找到一个更复杂的解决方案,为GCC的作品。但GCC的解决方案并不适用于Visual Studio工作。 :(但加入'的#ifdef __ __ GNUC',很容易选择一个给定的编译器设置宏的权利。
I was able to find a solution that worked for Visual Studio and Comeau compilers using extern character arrays. But I was able to find a more complex solution that works for GCC. But GCC's solution doesn't work for Visual Studio. :( But adding a '#ifdef __ GNUC __', it's easy to choose the right set of macros for a given compiler.
解决方案:
#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__ */
下面是报告 STATIC_ASSERT(1 == 1,test_message)的错误信息;在test.c的线路22
:
GCC:
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)
 &搜索NBSP;结果
原来的答案
我做的非常相似,跳棋做一些事情。但是我包括消息,将在许多编译器显示:
I do something very similar to what Checkers does. But I include a message that'll show up in many compilers:
#define STATIC_ASSERT(expr, msg) \
{ \
char STATIC_ASSERTION__##msg[(expr)?1:-1]; \
(void)STATIC_ASSERTION__##msg[0]; \
}
和在全球范围内做一些事情(在函数外)使用:
And for doing something at the global scope (outside a function) use this:
#define GLOBAL_STATIC_ASSERT(expr, msg) \
extern char STATIC_ASSERTION__##msg[1]; \
extern char STATIC_ASSERTION__##msg[(expr)?1:2]
这篇关于如何在构建时用C断言前pressions的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!