编译时大小有条件
如果涉及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 int
和int
具有相同的大小,您的示例可以像这样完成:
#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位)。