#ifdef用于32位平台

时间:2009-04-09 19:40:46

标签: c++ c gcc 64-bit 32-bit

在我维护的应用程序中,我们遇到了影响stdlib的文件描述符限制的问题。此问题仅影响标准库的32位版本。

我已经为我的代码设计了一个修复程序,并希望实现它,但只有在编译32位可执行文件时才能实现。我可以#ifdef使用什么预处理器符号来确定是为32位还是64位目标编译代码?

修改

很抱歉,没有提及,代码是跨平台,linux,windows,solaris和其他一些unix风格,大多使用GCC进行编译。我可以跨平台使用任何事实上的标准吗?

编辑2

我发现了一些似乎可能有用的定义“__ILP23”和“__LP64”......讨论here解释了unix平台的背景。任何人都有使用这些定义的经验吗?这可以用吗?

11 个答案:

答案 0 :(得分:16)

我不确定是否存在适合的通用#if def。 C ++标准几乎肯定没有定义一个。然而,肯定存在平台spcefic。

例如,Windows

#if _WIN64 
// 64 bit build
#else
// 32 bit build
#endif

编辑 OP提到这是使用GCC和其他编译器的Windows和非Windows之间的交叉编译

没有可用于所有平台和编译器的通用宏。一点点的预处理器魔术可以做到这一点。假设您只使用x86和amd64芯片,以下应该可以解决问题。它可以很容易地扩展到其他平台,但

#if _WIN64 || __amd64__
#define PORTABLE_64_BIT
#else
#define PORTABLE_32_BIT
#endif

答案 1 :(得分:13)

我建议为predef SourceForge添加书签。没有一个答案,但它肯定可以帮助你开始。

编辑:对于仅GCC代码,您可以使用__i386__检查32位x86芯片,我建议尝试使用__X86_64__或类似的东西来检查64位x86芯片。 (注意:我注意到前面涉及__ia86__的答案实际上是一个不同的芯片,而不是64位x86芯片。这只是表明我缺乏硬件经验。对于那些比我更了解硬件的人,使用我链接到上面的预定义宏的SourceForge页面。它比我更准确。)还有一些其他的可行,但这两个应该是相当普遍的GCC版本。

答案 2 :(得分:6)

看一下:

i386 macros
AMD64 macros

答案 3 :(得分:4)

你可以检查一个众所周知的类型,例如它的大小,例如对于32位平台,sizeof(int *)== 4。

由于sizeof在编译时已知,我相信

if(sizeof(int*) == 4)
{
  ...
}

应该做的伎俩

编辑:评论是正确的,您需要使用常规if,#if将无效。

如果您正在使用C ++您可以创建模板化代码,让编译器根据sizeof()调用为您选择专门化。 如果构建32位平台,编译器只会实例化32位平台的代码。 如果构建654位平台,编译器将只实例化64位平台的代码。

答案 4 :(得分:3)

我将通过最大指针值常量间接测试它:

#include <stdint.h>

#if UINTPTR_MAX == 0xffFFffFF
// 32-bit platform
#elif UINTPTR_MAX == 0xffFFffFFffFFffFF
// 64-bit platform
#else
#error Unknown platform - does not look either like 32-bit or 64-bit
#endif

这样,您就不必依赖于任何特定于平台的体系结构定义,而要依赖具有特定体系结构的直接结果-指针大小。

答案 5 :(得分:2)

我最终可能会做的是,在Makefile中,确定你是使用32位平台还是64位使用uname。然后,添加到CFLAGS,-DX32或-DX64。你可以#ifdef X64。

但这只是一个单一的解决方案。我不确定我会在Windows上做什么。

答案 6 :(得分:2)

至少32位Solaris的限制为256个文件指针,因为该结构将文件描述符存储在unsigned char字段中。保留这一点是为了向后兼容一些几乎不可能的旧版SunOS。其他平台 - 我很想说大多数其他平台 - 不会分享这个限制。另一方面,普通用户程序需要同时打开多个文件是相对不常见的;它通常表示一个错误(完成后不关闭文件)而不是。尽管如此,对于需要同时打开大量数据文件的数据库服务器这样的问题可能会出现问题。


一条评论说:

  

几乎就是这样。我们没有打开大量文件,但服务器处理来自客户端的大量连接。套接字句柄和文件描述符似乎来自同一个地方。当我们有很多连接时,'fopen'失败,因为系统级调用返回并且fd&gt; 255。

'套接字句柄'是系统调用级别的文件描述符,因此它们来自与文件的常规文件描述符相同的位置。

如果你必须解决这个问题,那么你需要包装你当前的套接字开放代码,这样如果它获得了0..255范围内的文件描述符,那么它会调用“dup2()”来创建一个stdio不会使用的范围内的文件描述符 - 然后关闭原始文件描述符。唯一的障碍是你必须跟踪哪些文件描述符可用,因为dup2将快速关闭目标文件描述符(如果它当前是打开的。)

当然,我假设您的套接字代码读取文件描述符而不是文件指针。如果是这种情况,那么你就会遇到更大的问题 - 太多的东西想要使用相同的资源而且他们不能同时使用它们。

答案 7 :(得分:1)

取决于您的操作系统和编译器,这些是实施决策。

答案 8 :(得分:1)

我在Windows中使用这样的结构:

#if defined(_WIN64)
   //64-bit code
#elif  defined(_M_IX86)
   //32-bit code
#else
#error "Unknown platform"
#endif

对战:

#if defined(_WIN64)
  // 64 bit code
#else
  // 32-bit code
#endif

在前一个解决方案中,由于#error,编译器将能够告诉您需要为新平台添加代码的位置。如果您遇到既不是64位也不是32位的平台,这有助于维护。是的,_M_IX86并不完全是32位的同义词,但我认为我们大多数人支持的唯一32位平台实际上是x86。因此,作为一项实际措施,它就足够了。

在后面的解决方案中,您必须使用grep或类似的东西手动找出您需要新平台代码的位置。这很乏味且容易出错。

我觉得以下结构也是可以接受的,虽然我没有在生产中测试它,也没有真正考虑过它。

#if defined(_WIN64)
   //64-bit code
#elif  defined(_WIN32)
   //32-bit code
#else
#error "Unknown platform"
#endif

答案 9 :(得分:0)

我相信定义是_WIN64

答案 10 :(得分:0)

C ++标准没有定义这样的符号 - 您的特定平台(您在问题中未指定)可以提供一个。