2009-08-17 10 views
5

Como dice el título, ¿existe alguna forma elegante y segura de determinar si la arquitectura es de 32 bits o de 64 bits? Por elegante, puede pensar en forma precisa, correcta, corta, limpia e inteligente. Por seguridad, piense en seguridad en términos de la norma, C89/C99, y la independencia del sistema operativo.Elegante y segura manera de determinar si la arquitectura es de 32 bits o 64 bits

+13

En C, la pregunta es ambigua: ¿desea saber si el código del programa es de código de 64 bits, o si la CPU soporta código de 64 bits (es decir, como en tiempo de compilación o una prueba de tiempo de ejecución)? –

+6

¿quieres decir en tiempo de compilación o en tiempo de ejecución? Cualquier sistema operativo específico? –

+1

La pregunta no puede responderse sin antes definir lo que quiere decir con una arquitectura de 32 bits o de 64 bits. No hay una definición universalmente aceptada. –

Respuesta

3

El tamaño de los punteros no es realmente algo bueno para probar: de todos modos, no hay mucho en la norma C que pueda hacer con el resultado de esa prueba.

Mi sugerencia es la prueba ((size_t)-1), el tamaño del objeto más grande que el C entiende:

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

Si es mayor que 0xffffffffUL entonces se puede, en principio, tener objetos más grandes que 2**32 - 1 bytes, lo que parece una prueba más significativa que un nebuloso "32 bits versus 64 bits".

(Por ejemplo, si se sabe que el valor máximo de size_t sólo es 2**32 - 1, entonces no hay razón para tratar de mmap() una región más grande que 1 o 2 GB.)

2

La forma más común es probar sizeof(void*) y sizeof(int) (tenga en cuenta que no tienen que ser necesariamente los mismos).

Otra posibilidad en las CPU x86/x64 es probar el indicador 'lm'. Si está presente, la CPU entiende el conjunto de instrucciones AMD64.

+0

Lo que sugiere es encontrar ambos tamaños y luego determinar la arquitectura. Otra sugerencia, para probar la bandera 'lm' suena que requiere un código ensamblador en C. ¿Correcto? – mtasic85

+1

Solo he visto la prueba de instrucciones específicas en el código (y fue ensamblador, sí). Sin embargo, muchos sistemas operativos exponen los indicadores de CPU en el área de usuario. Linux, por ejemplo, le da esta información en/proc/cpuinfo. Pero esto daría como resultado un código dependiente del sistema operativo. – ypnos

+1

¿Qué pasa si tienes una versión del compilador de 32 bits ejecutándose en una máquina de 64 bits, seguramente eso no funcionaría? – Matt

9

respuesta corta: sin

respuesta larga: depende de demasiadas combinaciones de OS/compilador. Por ejemplo, en tiempo de ejecución, en Linux puede consultar el sistema de archivos proc mientras que en Windows puede consultar el registro.

se puede demostrar que el compilador que se están utilizando para la compilación tiene un 32/64 bits objetivo usando algo como:

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

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

esto podría funciona bajo unos supuestos (por ejemplo, funciona en tiempo de ejecución). Puede buscar el tiempo de compilación #define para su plataforma, pero es un desastre bien conocido.

+0

Si activa la optimización no se evaluará en el tiempo de ejecución, se eliminará el código innecesario de 32/64 bits. Además, * bool * no está en ningún estándar C. – jbcreix

+5

"Además, bool no está en ningún estándar C". - falso, está en el estándar C99 en - http://en.wikipedia.org/wiki/Stdbool.h –

+0

oops. punto tomado, aún, no es C89 que se especifica en la pregunta, probablemente debido a este tipo de cosas extrañas en c99. – jbcreix

7

Si está utilizando GCC (como se indica en las etiquetas), se puede probar, como una prueba de tiempo de compilación

#if __SIZEOF_POINTER__ == 8 

para averiguar si se trata de un sistema de 64 bits. Asegúrese de que la versión de GCC que está utilizando define __SIZEOF_POINTER__ antes de usarlo.

+1

Esto soluciona el problema en tiempo de compilación para GCC, y está bien hasta el momento. – mtasic85

+1

+0 La respuesta de dfa es portable (una vez que elimina su tipo de bool extraño) y hará que el código sea más limpio. La función siempre devolverá verdadero o falso y el compilador eliminará el código innecesario. – jbcreix

2

Desafortunadamente, es imposible utilizar una técnica segura y portátil (porque seguro y portátil solo le permite las reglas del Estándar C).

sizeof(int) con algunos de los compiladores más comunes pueden darle 4 para una plataforma de 32 bits y 8 para una plataforma de 64 bits, pero esto no está garantizado. Todo lo que el estándar C dice es que un int debe ser el tamaño 'natural' para los cálculos en el destino, y tantos compiladores han dejado sizeof (int) como 4 incluso en un mundo de 64 bits, basándose en que es 'suficiente' '.

sizeof(void*) es mejor porque un puntero debe ser del tamaño adecuado para abordar todo el espacio de direcciones. sizeof(void*) es probable que le dé 4 u 8 según corresponda. Técnicamente, incluso esto no está garantizado ya que un sizeof le da la cantidad de bytes necesarios para almacenar algo, y un byte no tiene que ser de 8 bits. Un byte es, técnicamente, la unidad de memoria direccionable más pequeña que resulta ser de 8 bits en la mayoría de las plataformas a las que las personas están acostumbradas. 8 bits direccionables es muy común, pero trabajo con chips que son 16 bits direccionables y 16 bits de tamaño de palabra (entonces sizeof(int) es 1). Entonces, si el tamaño de su byte no es de 8 bits, entonces sizeof(void*) podría darle una variedad de valores.

Por otro lado, si usted está simplemente tratando de diferenciar entre x86 y x64 (32 bits y 64 bits procesadores de PC) a continuación, sizeof (void *) será suficiente, y portátil a través de compiladores.

+1

Puede multiplicar sizeof (void *) por CHAR_BIT para encontrar su tamaño en bits (aunque el estándar no garantiza que todos los bits en la representación sean bits de valor; de hecho, en las implementaciones x86_64 actuales solo suele haber un lugar en la región de 48 bits de valor en una dirección virtual). – caf

1

32-bits en el banco de código o 32 bits en el banco de datos. :-) Los procesadores 8086 tenían datos de 16 bits con memoria de código de 20 bits. Además, las modernas máquinas de Havard hacen cosas extrañas con la separación de códigos/datos ...

Puede consultar la instrucción cpuid para procesadores x86. Es posible que otras familias de procesadores no tengan esa instrucción ... YMMV.

1
int iedx; 

__asm 
{ 

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

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

la arquitectura de la computadora en la mayoría de los casos no se refiere a x86 y x86_64, sino a la arquitectura genérica. Este código no es estándar ni portátil. – osgx

Cuestiones relacionadas