19

如果涉及的条件为真,我想定义一个宏,sizeof如果它为假,则什么都不做(但仍然编译)。如果预处理器支持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如果编译失败)它失败了),但我看不到将这种方法扩展到我想要的方法。

4

9 回答 9

15

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

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

于 2010-12-07T07:54:03.937 回答
11

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

#include <stdint.h>
#include <inttypes.h>

您只需要两者之一,因为#include <inttypes.h>包括来自的材料#include <stdint.h>;但是,其中的许多材料<inttypes.h>仅与使用scanf()和格式化的 I/O 相关printf()

鉴于假定的条件:

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

您似乎追求的是:

uintptr_t

那是大到足以容纳任何指针的无符号整数类型(即,C 标准中的任何数据指针;POSIX 强加了一个附加规则,即它也必须足够大以容纳函数指针)。类型uintptr_t定义在<stdint.h>.

如果您随后要打印这些值或原始指针,您可以使用以下信息<inttypes.h>

printf("Pointer = 0x%" PRIXPTR "\n", uintptr_value);
printf("Pointer = 0x%" PRIXPTR "\n", (uintptr_t)any_pointer);
于 2010-12-07T08:11:09.207 回答
11

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

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

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

于 2012-02-14T21:48:20.640 回答
6

假设 C99,你可以使用

#include <limits.h>
#include <stdint.h>

#if UINTPTR_MAX <= UINT_MAX
...

这意味着sizeof (void *) <= sizeof (intptr_t) <= sizeof (int)C 语言的任何合理实现。

于 2010-12-07T09:27:02.437 回答
5

Given that the other answers already explained why sizeof cannot be used with #if, let me provide a simple solution for your case (surprisingly not yet mentioned). Take a look at

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

It mentions several predefined __SIZEOF_XYZ__ macros that actually can be used in preprocessing phase, i.e. also in #if. Assuming unsigned int and int are of same size, your example can be done like this:

#if __SIZEOF_POINTER__ == __SIZEOF_INT__
#define POINTER_FITS_INTO_UINT
#endif
于 2016-02-12T07:52:28.067 回答
4

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

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

static_assert (sizeof(int) <= sizeof(T), "T is not big enough!")
于 2010-12-07T10:00:41.953 回答
1

编辑

没关系,正如 Steve Rowe 指出的那样,这些预处理器值sizeof也会被设置,所以我们只是绕了一圈。

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

#include <values.h>
#if PTRBITS <= INTBITS
#  define POINTER_FITS_INTO_UINT
#endif
于 2010-12-07T07:55:06.517 回答
0

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

这是两个不同的二进制文件,您不能将这种类型的信息从一个传递到另一个。__i386__如果您想确定您所在的架构,然后推断 int 和指针大小,则必须使用系统定义的宏,例如__x86_64__。

于 2010-12-07T08:06:06.577 回答
0

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

There are several data models including LP32 ILP32 LP64 LLP64 ILP64 and on most platforms, the cc frontend command defines the current model (e.g. _ILP32 meaning int, long and pointer are 32bit while _LP64 means long and pointer are 64bit).

于 2015-08-12T20:02:02.547 回答