views:

568

answers:

7

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.

+2  A: 

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.

ypnos
What you suggest is to find both sizes and then determine architecture. Other suggestion, to test for the 'lm' flag sounds that it requires assembler code in C. Right?
mtasic
I've only seen the test for specific instructions in code (and it was assembler, yes). Many OSes expose the CPU flags in userland however. Linux for example gives you this information in /proc/cpuinfo. But this would result in OS dependent code.
ypnos
What if you've got a 32 bit compiler version running on a 64-bit machine, surely that wouldn't work?
Matt H
@Matt: You have to decide what you want. If you want information about the host system, try CPU flags. If you want information about the build architecture, use sizeof().
ypnos
+8  A: 

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.

dfa
If you turn optimization on it won't evaluate at runtime, unneeded 32/64 bits code will be removed. Also, *bool* is not in any C standard.
jbcreix
"Also, bool is not in any C standard." - false, it is in the C99 standard in <stdbool.h> - http://en.wikipedia.org/wiki/Stdbool.h
Peter Burns
oops. point taken, still, it isn't C89 which is specified in the question probably because of this kind of weird things in c99.
jbcreix
+2  A: 

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.

Martin v. Löwis
This solves problem at compile-time for GCC, and it is OK so far.
mtasic
+0 dfa's answer is portable(once you remove his extraneous bool type) and will make for cleaner code. The function will always return either true or false and the compiler will remove the unneeded code.
jbcreix
+2  A: 

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.

WillW
You can multiply sizeof(void *) by CHAR_BIT to find its size in bits (although but the standard doesn't guarantee that all the bits in the representation are value bits - in fact in current x86_64 implementations there's typically only somewhere in the region of 48 value bits in a virtual address).
caf
+1  A: 

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.)

caf
A: 

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.

Paul Nathan
+2  A: 
int iedx;

__asm
{

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

     if (iedx & (1 << 29))
       {
        return 1;
       }
     return 0;
Arabcoder
computer architecture in most times refers not to x86 and x86_64, but to generic architecture. This code is not standard and not portable.
osgx