tipos tamaño son significado rango que primitivos los lenguaje fundamentos derivados datos dato bytes c++ c linux compiler-construction operating-system

c++ - son - ¿Quién decide el tamaño de cualquier tipo de datos o estructura(dependiendo de 32 bits o 64 bits)?



tipos de datos primitivos en c (7)

Cuando habla sobre el compilador, debe tener una imagen limpia sobre build|host|target , es decir, la máquina en la que está construyendo (build), la máquina para la que está construyendo (host) y la máquina que GCC producirá el código para (destino), porque para "compilación cruzada" es muy diferente de "compilación nativa".

Acerca de la pregunta "quién decide el tamaño del tipo de datos y la estructura", depende del sistema de destino al que le ordenó al compilador que compile el binario. Si el objetivo es de 64 bits, el compilador traducirá sizeof (largo) a 8, y si el objetivo es una máquina de 32 bits, el compilador traducirá sizeof (largo) a 4. Todo esto ha sido predefinido por el archivo de encabezado que usó para compilar su programa Si lees tu `$ MAKETOP / usr / include / stdint.h '', hay typedefs para definir el tamaño de tu tipo de datos.

Para evitar el error creado por la diferencia de tamaño, los estilos de codificación de Google tipo Integer_types recomiendan el uso de tipos como int16_t, uint32_t, int64_t, etc. Estos se definieron en <stdint.h> .

Arriba solo están aquellos ''Datos antiguos y sencillos'', como int. Si se habla de una estructura, hay otra historia, porque el tamaño de una estructura depende de la alineación del relleno , la alineación de los límites de cada campo en la estructura, lo que tendrá un impacto en el tamaño de la estructura.

¿Quién decide el tamaño de cualquier tipo de datos o estructura (dependiendo de 32 bits o 64 bits)? ¿El compilador o el procesador? Por ejemplo, sizeof(int) es de 4 bytes para un sistema de 32 bits, mientras que es de 8 bytes para un sistema de 64 bits.

También leí que sizeof(int) es de 4 bytes cuando se compila utilizando un compilador de 32 y 64 bits .

Supongamos que mi CPU puede ejecutar aplicaciones tanto de 32 bits como de 64 bits. ¿Quién desempeñará el papel principal al decidir el tamaño de los datos del compilador o el procesador ?


El compilador decide qué tan grandes son los tipos básicos y cuál es el diseño de las estructuras. Si una biblioteca declara algún tipo, decidirá cómo se definen esos y, por lo tanto, qué tamaño tienen.

Sin embargo, a menudo es el caso que la compatibilidad con un estándar existente, y la necesidad de vincular a las bibliotecas existentes producidas por otros compiladores, obliga a una implementación determinada a tomar ciertas decisiones. Por ejemplo, el estándar de idioma dice que un wchar_t debe ser más ancho que 16 bits, y en Linux, tiene 32 bits de ancho, pero siempre ha sido 16 bits en Windows, por lo que los compiladores para Windows eligen ser compatibles con la API de Windows en lugar de la norma de lenguaje. Una gran cantidad de código heredado tanto para Linux como para Windows asume que un long tiene exactamente 32 bits de ancho, mientras que otro código asumió que era lo suficientemente ancho como para contener una marca de tiempo en segundos o una dirección IPv4 o un desplazamiento de archivo o los bits de un puntero, y (después de que un compilador definiera int en 64 bits de ancho y 32 bits de ancho), el lenguaje estándar creó una nueva regla que int no puede ser más amplia que long .

Como resultado, los compiladores principales de este siglo eligen definir int como 32 bits de ancho, pero históricamente algunos lo han definido como 16 bits, 18 bits, 32 bits, 64 bits y otros tamaños. Algunos compiladores le permiten elegir si el long será exactamente de 32 bits de ancho, como se supone en un código heredado, o tan ancho como un puntero, como se supone en otro código de legado.

Esto demuestra cómo las suposiciones que hace hoy, como que un tipo que siempre tiene 32 bits de ancho, podrían volver a morderlo en el futuro. Esto ya le ha ocurrido a las bases de código C dos veces, en las transiciones a códigos de 32 y 64 bits.

Pero, ¿qué deberías usar realmente?

El tipo int rara vez es útil en estos días. Por lo general, puede usar algún otro tipo que ofrezca una garantía más sólida de lo que obtendrá. (Tiene una ventaja: los tipos que no son tan anchos como un int podrían ampliarse automáticamente a int , lo que podría causar algunos errores realmente extraños cuando se mezclan los tipos firmados y no firmados, e int es el tipo más pequeño que se garantiza que no es más corto que int .)

Si está usando una API en particular, generalmente querrá usar el mismo tipo que usa. Existen numerosos tipos en la biblioteca estándar para fines específicos, como clock_t para las clock_t de reloj y time_t para el tiempo en segundos.

Si desea el tipo más rápido que tenga al menos 16 bits de ancho, eso es int_fast16_t , y hay otros tipos similares. (A menos que se especifique lo contrario, todos estos tipos se definen en <stdint.h> .) Si desea que el tipo más pequeño que tenga al menos 32 bits de ancho, int_least32_t la mayor cantidad de datos en sus arreglos, eso es int_least32_t . Si desea el tipo más amplio posible, ese es intmax_t . Si sabe que desea exactamente 32 bits, y su compilador tiene un tipo así , es int32_t Si desea algo que tenga 32 bits de ancho en una máquina de 32 bits y 64 bits de ancho en una máquina de 64 bits, y siempre el tamaño correcto para almacenar un puntero, eso es intptr_t . Si desea un buen tipo para hacer la indexación de matrices y el puntero matemático, eso es ptrdiff_t de <stddef.h> . (Este está en un encabezado diferente porque es de C89, no de C99).

Utilice el tipo que realmente quiere decir!


El diseñador del procesador determina qué registros e instrucciones están disponibles, cuáles son las reglas de alineación para un acceso eficiente, qué tan grandes son las direcciones de memoria y demás.

El estándar C establece los requisitos mínimos para los tipos incorporados. "char" debe tener al menos 8 bits, "short" e "int" deben tener al menos 16 bits, "long" debe ser de al menos 32 bits y "long long" debe ser de al menos 64 bits. También dice que "char" debe ser equivalente a la unidad de memoria más pequeña que el programa puede abordar y que debe mantenerse el orden de tamaño de los tipos estándar.

Otras normas también pueden tener un impacto. Por ejemplo, la versión 2 de la "especificación Unix única" dice que int debe tener al menos 32 bits.

Finalmente el código existente tiene un impacto. Portar ya es lo suficientemente difícil, nadie quiere hacerlo más difícil de lo necesario.

Al trasladar un sistema operativo y un compilador a una nueva CPU, alguien tiene que definir lo que se conoce como "C ABI". Esto define cómo el código binario se comunica entre sí, incluido.

  • El tamaño y los requisitos de alineación de los tipos incorporados.
  • Las reglas de embalaje para las estructuras (y por lo tanto, cuál será su tamaño).
  • Cómo se pasan y devuelven los parámetros
  • Cómo se maneja la pila

En general, una vez y ABI se define para una combinación de la familia de CPU y el sistema operativo, no cambia mucho (a veces el tamaño de los tipos más oscuros, como los cambios "dobles largos"). Cambiarlo trae un montón de roturas por una ganancia relativamente pequeña.

De manera similar, aquellos que trasladen un sistema operativo a una plataforma con características similares a una existente, generalmente elegirán los mismos tamaños que en las plataformas anteriores a las que el sistema operativo fue portado.

En la práctica, los proveedores de sistemas operativos / compiladores suelen instalarse en una de las pocas combinaciones de tamaños para los tipos de enteros básicos.

  • "LP32": char es de 8 bits. short y int son 16 bits, long y puntero son 32 bits. Comúnmente utilizado en plataformas de 8 y 16 bits.
  • "ILP32": char es de 8 bits, corto es de 16 bits. Int, long y puntero son todos 32 bits. Si existe mucho tiempo es 64 bit. Comúnmente utilizado en plataformas de 32 bits.
  • "LLP64": char es de 8 bits. corto es de 16 bits. Int y largos son 32 bits. Largo largo y puntero son 64 bits. Utilizado en ventanas de 64 bits.
  • "LP64": char es de 8 bits. corto es de 16 bits. int es de 32 bits. Largo, largo largo y puntero son 64 bits. Se utiliza en la mayoría de los sistemas similares a Unix de 64 bits.
  • "ILP64": char es de 8 bits, corto es de 16 bits, int, largo y puntero y largo es de 64 bits. Aparentemente se usa en algunos sistemas operativos tempranos de 64 bits pero raramente se ve hoy en día.

Los procesadores de 64 bits normalmente pueden ejecutar tanto binarios de 32 bits como de 64 bits. Generalmente esto se maneja al tener una capa de compatibilidad en su sistema operativo. Por lo tanto, su binario de 32 bits utiliza los mismos tipos de datos que usaría cuando se ejecuta en un sistema de 32 bits, luego la capa de compatibilidad traduce las llamadas del sistema para que el sistema operativo de 64 bits pueda manejarlas.


Es el compilador, y más precisamente su componente generador de código.

Por supuesto, el compilador es consciente de la arquitectura y hace elecciones que encajan con él.

En algunos casos, el trabajo se realiza en dos pases, uno en tiempo de compilación por un generador de código intermedio, y luego un segundo en tiempo de ejecución por un compilador justo a tiempo. Pero esto sigue siendo un compilador.


Es en definitiva el compilador. Los implementadores del compilador pueden decidir emular cualquier tamaño de entero que consideren adecuado, independientemente de lo que la CPU maneje de la manera más eficiente. Dicho esto, el estándar C (y C ++) está escrito de tal manera que el implementador del compilador es libre de elegir la forma más rápida y eficiente. Para muchos compiladores, los implementadores optaron por mantener int como un bit de 32 bits, aunque la CPU maneja de forma nativa 64 bits de manera muy eficiente.

Creo que esto se hizo en parte para aumentar la portabilidad hacia programas escritos cuando las máquinas de 32 bits eran las más comunes y quienes esperaban que un int fuera de 32 bits y no más. (También podría ser, como lo señala el usuario 3386109 , que se prefirieron los datos de 32 bits porque ocupa menos espacio y, por lo tanto, se puede acceder a ellos más rápido).

Por lo tanto, si desea asegurarse de obtener int64_t de 64 bits, use int64_t lugar de int para declarar su variable. Si sabe que su valor se ajustará a 32 bits o no le importa el tamaño, use int para que el compilador elija la representación más eficiente.

En cuanto a los otros tipos de datos, como struct , se componen de los tipos base, como int .


Es estrictamente, 100%, el compilador que decide el valor de sizeof (int). No es una combinación del sistema y el compilador. Es solo el compilador (y las especificaciones de lenguaje C / C ++).

Si desarrolla aplicaciones para iPad o iPhone, el compilador se ejecuta en su Mac. La Mac y el iPhone / iPac utilizan diferentes procesadores. Nada acerca de su Mac le dice al compilador qué tamaño debe usarse para int en el iPad.


No es la CPU, ni el compilador, ni el sistema operativo. Son los tres al mismo tiempo.

El compilador no puede simplemente hacer las cosas. Debe cumplir con el ABI derecho [1] que proporciona el sistema operativo. Si las estructuras y las llamadas al sistema provistas por el sistema operativo tienen tipos con ciertos tamaños y requisitos de alineación, el compilador no es realmente libre de crear su propia realidad a menos que los desarrolladores del compilador quieran volver a implementar las funciones de envoltorio para todo lo que el sistema operativo proporciona. Entonces, el ABI del sistema operativo no se puede recuperar completamente, tiene que hacer lo que se puede hacer razonablemente en la CPU. Y muy a menudo, el ABI de un sistema operativo será muy similar a otros ABI para otros sistemas operativos en la misma CPU porque es más fácil poder reutilizar el trabajo que hicieron (en compiladores, entre otras cosas).

En el caso de computadoras que admiten códigos de 32 y 64 bits, el sistema operativo aún debe realizar el trabajo para admitir la ejecución de programas en ambos modos (porque el sistema debe proporcionar dos ABI diferentes). Algunos sistemas operativos no lo hacen y en aquellos que no tienen otra opción.

[1] ABI significa Application Binary Interface. Es un conjunto de reglas sobre cómo un programa interactúa con el sistema operativo. Define cómo se almacena un programa en el disco para que pueda ejecutarse mediante el sistema operativo, cómo hacer llamadas al sistema, cómo vincular bibliotecas, etc. Pero para poder vincular bibliotecas, por ejemplo, su programa y la biblioteca tienen que estar de acuerdo. sobre cómo realizar llamadas de función entre su programa y la biblioteca (y viceversa) y para poder hacer llamadas de función, tanto el programa como la biblioteca deben tener la misma idea de diseño de pila, uso de registros, convenciones de llamada de funciones, etc. Y para las llamadas a funciones, debe acordar qué significan los parámetros y eso incluye los tamaños, la alineación y la firmeza de los tipos.