如果一个条件涉及sizeof
,我想定义一个宏,如果它是true,什么也不做(但仍然编译)。如果预处理器支持sizeof
,它看起来像这样:
#if (sizeof(void*) <= sizeof(unsigned int)) // what goes here?
# define POINTER_FITS_INTO_UINT
#endif
字符串
有一些页面(例如http://scaryreasoner.wordpress.com/2009/02/28/checking-sizeof-at-compile-time/)解释了如何在sizeof
上进行编译时 * Assert *(如果失败则无法编译),但我没有看到一种方法来扩展这种方法。
9条答案
按热度按时间wztqucjr1#
This描述了如何在C语言中伪造编译时Assert。简短的版本是使用switch语句:
字符串
如果
pred
的计算结果为0,就像C语言中的false布尔表达式一样,编译器将抛出一个错误。未来的更新:从C11开始,您可以只使用
型
从
assert.h
开始。ogsagwnx2#
假设C99,你可以使用
字符串
这意味着
sizeof (void *) <= sizeof (intptr_t) <= sizeof (int)
在任何正常的C语言实现上。l7wslrjt3#
考虑到其他答案已经解释了为什么
sizeof
不能与#if
一起使用,让我为您的情况提供一个简单的解决方案(令人惊讶的是尚未提到)。https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html#Common-Predefined-Macros.
它提到了几个预定义的
__SIZEOF_XYZ__
宏,这些宏实际上可以在预处理阶段使用,即也可以在#if
中使用。假设unsigned int
和int
的大小相同,您的示例可以这样做:字符串
zc0qhyus4#
尽管这个问题被标记为C而不是C++,但你可能会发现知道C++0x定义了一种由编译器而不是预处理器检查的静态Assert机制是很有帮助的。
维基百科的例子尤其相关:
字符串
tvokkenx5#
编辑
没关系,正如Steve Rowe指出的,这些预处理器值也由
sizeof
设置,所以我们只是兜了一个圈子。由于
sizeof
直到编译时才求值,因此需要依赖于其他预处理器值。我是这样做的:字符串
anauzrmj6#
你在这里混淆了两个编译步骤。当你编译一个C程序时,第一步是预处理器,它解析包括,宏,任何以'#'开头的行。然后是编译,它顺便计算表达式的大小。
这是两个不同的二进制文件,你不能把这种类型的信息从一个传递到另一个。你必须使用系统定义的宏,如
__i386__
或__x86_64__,如果你想弄清楚你在什么架构上,然后推导int和指针大小。e5njpo687#
理解这一点的一种方法是数据模型的概念(例如参见http://sourceforge.net/p/predef/wiki/DataModels/)。
有几种数据模型,包括LP 32 ILP32 LP 64 LLP64 ILP64,在大多数平台上,cc前端命令定义了当前模型(例如_ILP32表示int,long和指针是32位,而_LP 64表示long和指针是64位)。
m1m5dgzv8#
sizeof是一个编译时操作符。#if和#define与预处理器相关。由于预处理器在编译器之前运行,因此这不起作用。然而,您可能会找到一个《双城之战》编译器开关,允许您多遍传递它(即预处理,假装编译,预处理,编译)但是,公平地说,我会给予尝试做你想要的。它不意味着工作,简单地说,它不。
你最好的办法是将这些定义设置为传递给编译器的-D命令。你可以静态地Assert所选择的命令是正确的。这样你只需要在外部为给定的编译模式(例如PowerPC Release)设置一些定义,等等。
cotxawn79#
正确的解决方案是使用C99标准头:
字符串
您只需要这两个中的一个,因为
#include <inttypes.h>
包含了#include <stdint.h>
中的内容;但是,<inttypes.h>
中的许多内容只与scanf()
和printf()
的格式化I/O相关。假设条件:
型
你所追求的是:
型
这是一个无符号整数类型,它足够大,可以容纳任何指针(也就是说,C标准中的任何数据指针; POSIX强加了一个额外的规则,它也必须足够大,可以容纳函数指针)。
如果您随后要打印这些值或原始指针,您可以使用来自
<inttypes.h>
的信息:型