27

In a C++ function I need the compiler to choose a different block if it is compiling for a 64 bit architecture.

I know a way to do it for MSVC++ and g++, so I'll post it as an answer. However I would like to know if there is a better way (more elegant that would work for all compilers/all 64 bits architectures). If there is not a better way, what other predefined macros should I look for in order to be compatible with other compiler/architectures?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Mathieu Pagé
  • 10,764
  • 13
  • 48
  • 71
  • Similar question asked [here on SO](http://stackoverflow.com/questions/152016/detecting-cpu-architecture-compile-time)... with a really great answer. – oz10 Oct 29 '08 at 02:41

8 Answers8

38

An architecture-independent way to detect 32-bit and 64-bit builds in C and C++ looks like this:

// C
#include <stdint.h>

// C++
#include <cstdint>

#if INTPTR_MAX == INT64_MAX
// 64-bit
#elif INTPTR_MAX == INT32_MAX
// 32-bit
#else
#error Unknown pointer size or missing size macros!
#endif
DarkDust
  • 90,870
  • 19
  • 190
  • 224
  • And you could even add stuff for 16-bit and 8-bit CPUs! Definite upvote for this. – S.S. Anne Apr 01 '19 at 00:15
  • The C++ part requeries C++11 or later. Try with `-std=c++03` and GCC and you'll see: `error: #error This file requires compiler and library support for the ISO C++ 2011 standard. This support must be enabled with the -std=c++11 or -std=gnu++11 compiler options.` – Sebastian Apr 20 '21 at 18:44
  • Amazingly for gcc and Linux `` itself uses `__WORDSIZE` like `#if __WORDSIZE == 64`. And `wordsize.h` uses `if defined __x86_64__ && !defined __ILP32__`. – U. Windl May 18 '21 at 12:53
23

This works for MSVC++ and g++:

#if defined(_M_X64) || defined(__amd64__)
  // code...
#endif
S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
Mathieu Pagé
  • 10,764
  • 13
  • 48
  • 71
7

Why are you choosing one block over the other? If your decision is based on the size of a pointer, use sizeof(void*) == 8. If your decision is based on the size of an integer, use sizeof(int) == 8.

My point is that the name of the architecture itself should rarely make any difference. You check only what you need to check, for the purposes of what you are going to do. Your question does not cover very clearly what your purpose of the check is. What you are asking is akin to trying to determine if DirectX is installed by querying the version of Windows. You have more portable and generic tools at your disposal.

flodin
  • 5,215
  • 4
  • 26
  • 39
  • 2
    sizeof(int) isn't good example. It depends on compiler. I tried on 64 bit linux with g++ and it was 4 bytes long. Better use sizeof(void*) to determine architecutre. But im not sure if it is the same on all machines. – klew Feb 15 '09 at 17:24
  • 1
    @klew, I think you missed flodin's point: "You check only what you need to check, for the purposes of what you are going to do." – foraidt Mar 30 '09 at 14:13
  • But neither works in preprocessor e.g. `#if sizeof(int)==4` -- since the preprocessor doesn't allow `sizeof` in #if expressions. – greggo Oct 15 '14 at 16:28
  • 3
    @greggo You can use e.g. INT_MAX instead. See for example [](http://en.cppreference.com/w/cpp/types/climits). – flodin Oct 15 '14 at 19:35
  • @klew Yeah, `int` will always be 32 bits long no matter what architecture for backwards compatibility. `int64_t` (`uint64_t` for unsigned) is required for 64 bit numbers. – FluorescentGreen5 Sep 25 '16 at 06:39
  • The purpose of the check is clearly outside the scope of the question. It doesn't matter. However "rare" such need is in your estimation, cases where its needed do exist. – Swiss Frank Feb 02 '20 at 13:01
6

Raymond covers this.

GSerg
  • 76,472
  • 17
  • 159
  • 346
  • This is Visual C++-specific. – rdb Nov 22 '14 at 13:20
  • @rdb The first part is, then it goes *If you don't want to tie yourself to a particular compiler, you'll have to ...* – GSerg Nov 22 '14 at 15:59
  • That article is misleading and wrong! Try `ifdef _X86_` in visual studio without including anything. – Pavel P Mar 04 '18 at 22:00
  • @Pavel With all due respect, you have to learn a lot before you get to say that Raymond Chen's article is misleading and wrong. Regarding `_X86_` he is explicitly saying: `// assumes you use makefile.def [from the Windows DDK mentioned in the previous sentence]`, which is [where it is defined](https://stackoverflow.com/a/17761728/11683). – GSerg Mar 05 '18 at 06:48
  • @GSerg thanks for pointing out, I just read his article. He is totally correct, your answer is wrong and misleading. – Pavel P Mar 05 '18 at 06:53
  • 1
    The link is now broken. The article has moved to https://devblogs.microsoft.com/oldnewthing/20060906-07/?p=29843 – Max Barraclough Mar 10 '21 at 12:13
3

If you're compiling for the Windows platform, you should use:

#ifdef _WIN64

The MSVC compiler defines that for both x64 and ia64 platforms (you don't want to cut out that market, do you?). I'm not sure if gcc does the same - but it should if it doesn't.

An alternative is

#ifdef WIN64

which has a subtle difference. WIN64 (without the leading underscore) is defined by the SDK (or the build configuration). Since this is defined by the SDK/build config, it should work just as well with gcc.

Michael Burr
  • 333,147
  • 50
  • 533
  • 760
  • For what its worth WIN64 and WIN32 didnt work in VS Studio 19 in the year 2023. However _WIN32 AND _WIN64 work fine – LFMekz May 13 '23 at 00:56
2
#ifdef _LP64

Works on both platforms

1

Here's a good overview for Mac OS X:

http://developer.apple.com/documentation/Darwin/Conceptual/64bitPorting

mike511
  • 1,685
  • 4
  • 16
  • 18
-4

If your using Windows, your probably better to get the "PROCESSOR_ARCHITECTURE" environment variable from the registry because sizeof(PVOID) will equal 4 if its a 32bit process running on a 64bit operating system (aka WOW64):

    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SYSTEM\CurrentControlSet\\Control\\Session Manager\\Environment"), 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
        LPSTR szArch = new CHAR[100];

        ZeroMemory(szArch, 100);

        if (RegQueryValueEx(hKey, _T("PROCESSOR_ARCHITECTURE"), NULL, NULL, (LPBYTE)szArch, &dwSize) == ERROR_SUCCESS) {
            if (strcmp(szArch, "AMD64") == 0)
                this->nArchitecture = 64;
            else
                this->nArchitecture = 32;
        } else {
            this->nArchitecture = (sizeof(PVOID) == 4 ? 32 : 64);
        }

        RegCloseKey(hKey);
    }
SameOldNick
  • 2,397
  • 24
  • 33