有没有办法sizeof在预处理器宏中使用?
例如,多年来我一直有很多情况需要做以下事情:
#if sizeof(someThing) != PAGE_SIZE
#error Data structure doesn't match page size
#endif
Run Code Online (Sandbox Code Playgroud)
我在这里检查的确切内容是完全弥补的 - 重点是,我经常喜欢在这些类型的(大小或对齐)编译时检查,以防止某人修改数据结构可能会错位或重新大小会破坏它们的东西.
不用说 - 我似乎无法以sizeof上述方式使用a .
nev*_*ind 59
有几种方法可以做到这一点.如果sizeof(someThing)等于PAGE_SIZE,则以下代码段将不会生成代码; 否则会产生编译时错误.
从C11开始,您可以使用static_assert(要求#include <assert.h>).
用法:
static_assert(sizeof(someThing) == PAGE_SIZE, "Data structure doesn't match page size");
Run Code Online (Sandbox Code Playgroud)
如果您只是想在sizeof(something)不符合预期的情况下获得编译时错误,可以使用以下宏:
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
Run Code Online (Sandbox Code Playgroud)
用法:
BUILD_BUG_ON( sizeof(someThing) != PAGE_SIZE );
Run Code Online (Sandbox Code Playgroud)
本文详细解释了它的工作原理.
在Microsoft C++编译器上,您可以使用C_ASSERT宏(需要#include <windows.h>),它使用类似于第2节中描述的技巧.
用法:
C_ASSERT(sizeof(someThing) == PAGE_SIZE);
Run Code Online (Sandbox Code Playgroud)
我知道这个帖子真的很旧但是......
我的解决方案
extern char __CHECK__[1/!(<<EXPRESSION THAT SHOULD COME TO ZERO>>)];
Run Code Online (Sandbox Code Playgroud)
只要该表达式等于零,它就可以很好地编译.还有别的东西,就在那里爆炸了.因为变量是extern'd,它将不占用任何空间,并且只要没有人引用它(它们不会)它就不会导致链接错误.
不像assert宏那么灵活,但是我无法在我的GCC版本中编译,这将...而且我认为它将在任何地方编译.
小智 7
我知道这是一个迟到的答案,但是要添加到Mike的版本,这是我们使用的不分配任何内存的版本.我没有拿出原始尺寸检查,我几年前在互联网上找到它,不幸的是无法引用作者.另外两个只是同一个想法的扩展.
因为它们是typedef,所以没有分配.使用名称中的__LINE__,它始终是一个不同的名称,因此可以在需要时复制和粘贴它.这适用于MS Visual Studio C编译器和GCC Arm编译器.它在CodeWarrior中不起作用,CW抱怨重新定义,而不是使用__LINE__预处理器结构.
//Check overall structure size
typedef char p__LINE__[ (sizeof(PARS) == 4184) ? 1 : -1];
//check 8 byte alignment for flash write or similar
typedef char p__LINE__[ ((sizeof(PARS) % 8) == 0) ? 1 : 1];
//check offset in structure to ensure a piece didn't move
typedef char p__LINE__[ (offsetof(PARS, SUB_PARS) == 912) ? 1 : -1];
Run Code Online (Sandbox Code Playgroud)
现有的答案只是展示了如何根据类型的大小实现“编译时断言”的效果。在这种特殊情况下,这可能满足 OP 的需求,但在其他情况下,您确实需要一个基于类型大小的预处理器。这是如何做到的:
为自己编写一个小 C 程序,例如:
/* you could call this sizeof_int.c if you like... */
#include <stdio.h>
/* 'int' is just an example, it could be any other type */
int main(void) { printf("%zd", sizeof(int); }
Run Code Online (Sandbox Code Playgroud)
编译那个。用您最喜欢的脚本语言编写一个脚本,该脚本运行上述 C 程序并捕获其输出。使用该输出生成 C 头文件。例如,如果您使用的是 Ruby,它可能如下所示:
sizeof_int = `./sizeof_int`
File.open('include/sizes.h','w') { |f| f.write(<<HEADER) }
/* COMPUTER-GENERATED, DO NOT EDIT BY HAND! */
#define SIZEOF_INT #{sizeof_int}
/* others can go here... */
HEADER
Run Code Online (Sandbox Code Playgroud)
然后将规则添加到您的 Makefile 或其他构建脚本中,这将使其运行上述脚本以构建sizes.h.
包括sizes.h您需要根据大小使用预处理器条件的任何地方。
完毕!
(你有没有打字./configure && make来构建程序?configure脚本所做的基本上就像上面一样......)