C++ #ifdef 用于 32 位平台

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/735647/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 17:01:42  来源:igfitidea点击:

#ifdef for 32-bit platform

c++cgcc64-bit32-bit

提问by veefu

In an application I maintain, we've encountered a problem with file descriptor limitations affecting the stdlib. This problem only affects the 32-bit version of the standard lib.

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

I have devised a fix for my code and would like to implement it, but only when compiling for 32-bit executable. What pre-processor symbol can I #ifdef for to determine whether the code is being compiled for a 32 or 64-bit target?

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

EDIT

编辑

Sorry, didn't mention, the code is cross-platform, linux, windows, solaris and a few other unix flavors, mostly using GCC for compilation. Any de-facto standards I can use cross-platform?

不好意思,没提,代码是跨平台的,linux,windows,solaris等一些unix的风格,大部分是用GCC编译的。我可以使用跨平台的任何事实上的标准吗?

EDIT 2

编辑 2

I've found some definitions "__ILP23" and "__LP64" that seem like they may work... a discussion hereexplains the background on the unix platform. Anyone had any experience with using these defines? Is this going to be usable?

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

采纳答案by JaredPar

I'm not sure if there is a universal #if def that is appropriate. The C++ standard almost certainly does not define one. There are certainly platform spcefic ones though.

我不确定是否有合适的通用 #if def。C++ 标准几乎肯定没有定义。虽然肯定有平台特定的。

For example, Windows

例如,Windows

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

EDITOP mentioned this is a cross compile between Windows and Non-Windows using GCC and other compilers

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

There is no universal macro that can be used for all platforms and compilers. A little bit of preprocessor magic though can do the trick. Assuming you're only working on x86 and amd64 chips the following should do the trick. It can easily be expanded for other platforms though

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

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

回答by Chris Lutz

I recommend bookmarking the predef SourceForge. There's no one answer, but it can certainly help you get started.

我建议将predef SourceForge加入书签。没有一个答案,但它肯定可以帮助您入门。

EDIT: For GCC-only code, you can use __i386__to check for 32-bit x86 chips, and I suggest trying __X86_64__or something similar to check for 64-bit x86 chips. (Note: It has come to my attention that the previous answer involving __ia86__is actually a different chip, not a 64-bit x86 chip. This just shows my lack of hardware experience. For those more knowledgeable about hardware than I, consule the SourceForge page on predefined macros that I link to above. It's much more accurate than I am.) There are some other ones that would work, but those two should be fairly universal amongs GCC versions.

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

回答by Bastien Léonard

Have a look at that:

看看那个:

i386 macros
AMD64 macros

i386 宏
AMD64 宏

回答by lothar

You could check a well known type for it's size e.g. sizeof(int*) == 4 for a 32 bit platform.

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

As sizeof is known at compiletime I believe a

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

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

should do the trick

应该做的伎俩

Edit: the comments are right, you need to use a regular if, #if won't work.

编辑:评论是对的,您需要使用常规的 if,#if 不起作用。

If you are using C++ You could create templated code and let the compiler choose the specialization for you based on the sizeof() call. If you build for a 32 bit platform the compiler would only instantiate the code for the 32 bit platform. If you build for a 654 bit platform the compiler would only instantiate the code for the 64 bit platform.

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

回答by dragonroot

I would test it indirectly, via the maximum pointer value constant:

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

#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

This way you don't rely on any platform-specific define for architecture, but on the direct consequence of having a specific architecture - the pointer size.

通过这种方式,您不依赖于任何特定于平台的架构定义,而是依赖于具有特定架构的直接结果 - 指针大小。

回答by Bill Lynch

What I would probably end up doing, is within a Makefile, determine if you are on a 32 bit platform or 64 bit using uname. Then, add to your CFLAGS, -DX32, or -DX64. That you could just #ifdef X64.

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

But this is just a unixy solution. I'm not sure what I would do on windows.

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

回答by Jonathan Leffler

At least 32-bit Solaris has a limit of 256 file pointers because the structure stores the file descriptor in an unsigned char field. This is retained for backwards compatibility with some almost impossibly old versions of SunOS. Other platforms - I'm tempted to say most other platforms - do not share that limitation. On the other hand, it is relatively unusual for an ordinary user program to need that many files open concurrently; it more often indicates a bug (not closing the files when finished with them) than not. Having said that, though, it can be a problem for things like database servers which need to have lots of data files open at the same time.

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



One comment says:

一条评论说:

That's almost it. We don't have a large number of files open, but the server handles a large number of connections from clients. Socket handles and file descriptors seem to come from the same place. When we have a lot of connections, 'fopen' fails because the system-level call returns and fd > 255.

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

'Socket handles' are file descriptors at the system call level, so they come from the same place as regular file descriptors for files.

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

If you have to work around this, then you need to wrap your current socket opening code so that if it gets an file descriptor in the range 0..255, then it calls 'dup2()' to create a file descriptor in the range that stdio won't use - and then close the original file descriptor. The only snag with this is that you have to keep track of which file descriptors are available, because dup2will merrily close the target file descriptor if it is currently open.

如果您必须解决这个问题,那么您需要包装当前的套接字打开代码,以便如果它获得 0..255 范围内的文件描述符,则它会调用 ' dup2()' 在 stdio 赢得的范围内创建一个文件描述符't use - 然后关闭原始文件描述符。唯一的障碍是您必须跟踪哪些文件描述符可用,因为dup2如果目标文件描述符当前打开,它将愉快地关闭。

Of course, I'm assuming your socket code reads file descriptors and not file pointers. If that's the case, you have bigger problems - too many things want to use the same resources and they can't all use them at the same time.

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

回答by Craig Wright

I use a construction like this for Windows:

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

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

Versus:

相对:

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

In the former solution, because of the #error the compiler will be able to tell you where you need to add code for a new platform. This aids maintainability should you ever encounter a platform that is neither 64-bit nor 32-bit. Yes, the _M_IX86 is not exactly synonymous with 32-bit, but I think the only 32-bit platform most of us are supporting is in fact x86. So as a practical measure it suffices.

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

In the later solution you'll have to manually figure out where you need code for your new platform using grep or something like that. This is tedious and error prone.

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

It occurs to me that the following construction would also be acceptable, although I have not tested it in production nor I have really thought about it very much.

我突然想到以下构造也是可以接受的,尽管我没有在生产中对其进行测试,也没有真正考虑过它。

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

回答by Charlie Martin

Depends on your OS and compiler, those are implementation decisions.

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

回答by Charlie Martin

There is no such symbol defined by the C++ standard - your specific platform (which you haven't specified in your question) may provide one.

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