Elegant and safe way to determine if architecture

2019-02-22 16:08发布

问题:

As title says, is there any elegant and safe way to determine if architecture is 32bit or 64bit. By elegant, you can think of precise, correct, short, clean, and smart way. By safe, think of safe in term of standard, C89/C99, and operating system independence.

回答1:

The size of pointers isn't really a good thing to test - there's not much in standard C that you can do with the result of that test anyway.

My suggestion is test ((size_t)-1), the largest object size that C understands:

    if ((size_t)-1 > 0xffffffffUL)
    {
            printf("> 32 bits\n");
    }
    else
    {
            printf("<= 32 bits\n");
    }

If it's greater than 0xffffffffUL then you can in principle have objects larger than 2**32 - 1 bytes, which seems like a more meaningful test than a nebulous "32 bits versus 64 bits".

(For example, if you know that the maximum value of size_t is only 2**32 - 1, then there's no point trying to mmap() a region bigger than 1 or 2 GB.)



回答2:

short answer: no

long answer: it depends on too many OS/compiler combinations. For example at runtime, on linux you can query the proc filesystem whereas on windows you can query the register.

You can prove that the compiler that are being used for compilation has a 32/64 bits target using something like:

bool is_32bit() {
    return sizeof(int *) == 4;
} 

bool is_64bit() {
    return sizeof(int *) == 8;
} 

this could works under few assumptions (e.g. it works at runtime). You can search for compile-time #define for your platform but it is a well-known mess.



回答3:

If you are using GCC (as indicated in the tags), you can test, as a compile-time test

#if __SIZEOF_POINTER__ == 8

to find out whether it's a 64-bit system. Make sure the GCC version you are using defines __SIZEOF_POINTER__ at all before using it.



回答4:

The most common way is to test sizeof(void*) and sizeof(int) (note that they do not necessarily have to be the same).

Another possibility on x86/x64 CPUs is to test for the 'lm' flag. If it is present the CPU understands the AMD64 instruction set.



回答5:

A safe and portable technique is unfortunately impossible (because safe and portable only allows you the rules in the C Standard).

sizeof(int) with some of the more common compilers may give you 4 for a 32 bit platform and 8 for a 64 bit platform but this is not guaranteed. All the C standard says is that an int should be the 'natural' size for calculations on the target, and so many compilers have left sizeof(int) as 4 even in a 64 bit world, on the grounds that it is 'enough'.

sizeof(void*) is better because a pointer must be the appropriate size to address the whole address space. sizeof(void*) is therefore likely to give you 4 or 8 as appropriate. Technically though, even this isn't guaranteed as a sizeof gives you the number of bytes needed to store something, and a byte doesn't have to be 8 bits. A byte is technically the smallest addressable unit of memory which just happens to be 8 bits on most platforms people are used to. 8 bit addressable is very common, but I work with chips that are 16 bit addressable and 16 bit word size (so sizeof(int) is 1). So, if your byte size is not 8 bit, then sizeof(void*) could give you a variety of values.

On the other hand, if you are merely trying to differentiate between x86 and x64 (32bit and 64 bit PC processors) then sizeof(void*) will be sufficient, and portable across compilers.



回答6:

32-bit on the code bank or 32-bit on the data bank. :-) 8086 processors had 16-bit data with 20-bit code memory. Also, modern Havard machines do odd things with code/data separation...

You might check the cpuid instruction for x86 processors. Other processor families may not have such an instruction...YMMV.



回答7:

int iedx;

__asm
{

mov eax, 0x80000001;
cpuid;
mov, iedx,edx;
}

     if (iedx & (1 << 29))
       {
        return 1;
       }
     return 0;