编译时大小有条件

如果涉及sizeof的条件为true,我想定义一个宏,如果它为false,则不执行任何操作(但仍然编译)。 如果预处理器支持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上进行编译时断言 (并且无法编译)如果它失败了),但我没有看到将这种方法扩展到我想要的方法。

你不能这样做。 sizeof是一个编译时运算符。 #if和#define以及预处理器相关。 由于预处理器在编译器之前运行,因此不起作用。 但是,您可以找到一个神秘的编译器开关,它允许您多次传递它(即预处理,假装编译,预处理,编译)但是,平心而论,我放弃尝试做你想做的事情。 它并不意味着工作,简单地说,它没有。

最好的方法是将这样的定义设置为传递给编译器的-D命令。 您可以静态断言所选择的是正确的。 这样,您只需在外部为给定的编译模式(例如PowerPC Release)设置一些定义,依此类推。

您的问题的正确解决方案是使用C99标准标头:

 #include  #include  

您只需要两个中的一个,因为#include 包含来自#include 的材料; 但是, 的很多材料只与scanf()printf()格式化I / O相关。

鉴于推定的条件:

 #if (sizeof(void*) <= sizeof(unsigned int)) // what goes here? # define POINTER_FITS_INTO_UINT #endif 

您似乎追求的是:

 uintptr_t 

这是无符号整数类型,足以容纳任何指针(即C标准中的任何数据指针; POSIX强加了一个额外的规则,它也必须足够大以容纳函数指针)。 uintptr_t定义。

如果您随后要打印此类值或原始指针,则可以使用的信息:

 printf("Pointer = 0x%" PRIXPTR "\n", uintptr_value); printf("Pointer = 0x%" PRIXPTR "\n", (uintptr_t)any_pointer); 

这描述了如何在C中伪造编译时断言。简短版本是使用switch语句:

 #define COMPILE_TIME_ASSERT(pred) \ switch(0){case 0:case pred:;} 

如果pred计算结果为0,就像C中的假布尔表达式一样,编译器将抛出错误。

假设C99,你可以使用

 #include  #include  #if UINTPTR_MAX <= UINT_MAX ... 

这意味着在任何理智的C语言实现上, sizeof (void *) <= sizeof (intptr_t) <= sizeof (int)

即使问题是标记C而不是C ++,您可能会发现知道C ++ 0x定义静态断言的机制很有帮助,静态断言由编译器检查,而不是预处理器。

维基百科的例子特别相关:

 static_assert (sizeof(int) <= sizeof(T), "T is not big enough!") 

鉴于其他答案已经解释了为什么sizof不能与#if一起使用,让我为你的案例提供一个简单的解决方案(令人惊讶的是还没有提到)。 看一眼

https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html#Common-Predefined-Macros

它提到了几个预定义的__SIZEOF_XYZ__宏,它们实际上可以在预处理阶段使用,也就是在#if 。 假设unsigned intint具有相同的大小,您的示例可以像这样完成:

 #if __SIZEOF_POINTER__ == __SIZEOF_INT__ #define POINTER_FITS_INTO_UINT #endif 

编辑

没关系,正如Steve Rowe所指出的那样,这些预处理器值也是由sizeof设置的,所以我们只是完全循环。

由于sizeof直到编译时才进行评估,因此您需要依赖其他预处理器值。 我是这样做的:

 #include  #if PTRBITS <= INTBITS # define POINTER_FITS_INTO_UINT #endif 

你在这里混淆了两个编译步骤。 编译C程序时,第一步是预处理器,它解析包含宏,任何以’#’开头的行。 然后是编译,偶然评估sizeof表达式。

这是两个不同的二进制文件,您无法将这类信息从一个传递到另一个。 如果要了解所使用的体系结构,然后推导出int和指针大小,则必须使用系统定义的宏,例如__i386__或__x86_64__。

理解这一点的一种方法是数据模型的概念(参见例如http://sourceforge.net/p/predef/wiki/DataModels/ )。

有几种数据模型,包括LP32 ILP32 LP64 LLP64 ILP64,在大多数平台上,cc前端命令定义了当前模型(例如_ILP32表示int,long和指针是32位,而_LP64表示长,指针是64位)。