¿Es el tamaño de C "int" 2 bytes o 4 bytes?

169

¿Una variable entera en C ocupa 2 bytes o 4 bytes? ¿Cuáles son los factores de los que depende?

La mayoría de los libros de texto dicen que las variables enteras ocupan 2 bytes. Pero cuando ejecuto un programa que imprime las direcciones sucesivas de una serie de enteros, muestra la diferencia de 4.

Rajiv Prathap
fuente
66
en.wikipedia.org/wiki/…
Evan Mulawski
1
intes solo uno de varios tipos enteros . Usted preguntó sobre el tamaño de "entero"; probablemente querías preguntar sobre el tamaño de int.
Keith Thompson
3
Y deberías encontrar mejores libros de texto. Un libro de texto que dice que un intes de 2 bytes (a) probablemente se refiere a un sistema antiguo y (b) no deja en claro que el tamaño variará de un sistema a otro. El mejor libro sobre C es "El lenguaje de programación C" de Kernighan y Ritchie, aunque supone algo de experiencia en programación. Ver también la pregunta 18.10 de la FAQ comp.lang.c .
Keith Thompson
2
Pruébelo #define int int64_ten una plataforma de 64 bits, así que tampoco. Solo úsalo sizeof. ;-)
netcoder

Respuestas:

183

Sé que es igual a sizeof(int). El tamaño de un intes realmente dependiente del compilador. En el pasado, cuando los procesadores eran de 16 bits, un intera de 2 bytes. Hoy en día, con mayor frecuencia son 4 bytes en sistemas de 32 bits y de 64 bits.

Aún así, usar sizeof(int)es la mejor manera de obtener el tamaño de un número entero para el sistema específico en el que se ejecuta el programa.

EDITAR: Se corrigió una declaración incorrecta que intes de 8 bytes en la mayoría de los sistemas de 64 bits. Por ejemplo, son 4 bytes en GCC de 64 bits.

yhyrcanus
fuente
31
@RajivPrathap: Bueno, depende del compilador, pero el compilador decide si también depende o no de la máquina. :)
user541686
2
Si necesita el tamaño del preprocesador, puede verificar las macros predefinidas como INT_MAX. Si el valor no es el esperado por su código, entonces el tamaño de byte de int es diferente en la combinación actual de compilador / plataforma.
Walt Sellers
3
No solo depende de la máquina, sino que también depende del sistema operativo que se ejecuta en la máquina. Por ejemplo, el largo en Win64 es de 4 bytes, mientras que el largo en Linux64 es de 8 bytes.
Cem Kalyoncu
9
incorrecto. en la mayoría de los sistemas de 64 bits, int todavía tiene 4 bytes en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models
phuclv
77
sizeof(int)puede ser cualquier valor de 1. No se requiere que un byte sea de 8 bits y algunas máquinas no tienen una unidad direccionable de 8 bits (que básicamente es la definición de un byte en el estándar). La respuesta no es correcta sin más información.
demasiado honesto para este sitio
103

Este es uno de los puntos en C que puede ser confuso al principio, pero el estándar C solo especifica un rango mínimo para tipos enteros que se garantiza que es compatible. intse garantiza que puede contener -32767 a 32767, lo que requiere 16 bits. En ese caso int, es de 2 bytes. Sin embargo, las implementaciones son libres de ir más allá de ese mínimo, ya que verá que muchos compiladores modernos hacen int32 bits (lo que también significa 4 bytes bastante ubicuamente).

La razón por la que su libro dice 2 bytes es probablemente porque es antigua. En un momento, esta era la norma. En general, siempre debe usar el sizeofoperador si necesita averiguar cuántos bytes hay en la plataforma que está usando.

Para abordar esto, C99 agregó nuevos tipos donde puede solicitar explícitamente un número entero de cierto tamaño, por ejemplo int16_to int32_t. Antes de eso, no había una forma universal de obtener un número entero de un ancho específico (aunque la mayoría de las plataformas proporcionaban tipos similares por plataforma).

Error fatal
fuente
77
@nevanking: en una máquina complementaria de dos (que es cada máquina que conozco ...), sí. Pero, C no garantiza que sea el caso.
FatalError
@nevanking Soy completamente nuevo en C, pero ¿no es 32767 porque de lo contrario estaría usando otro bit | byte? Imagínese, puedo contener 3 dígitos (0 o 1), por lo que puedo pasar de 000 a 111 (que es decimal 7). 7 está justo antes de un exponente de 2. Si pudiera ir hasta 8 (1000), ¡podría usar esos 4 dígitos hasta 15! Tal como 32767 está justo antes de un exponente de 2, agotando todos los bits | bytes que tiene disponibles.
RGS
3
@RSerrao Tampoco soy un experto en C pero AFAIK para números positivos es uno menos que el número negativo máximo. Entonces -8 a 7, -256 a 255 y así sucesivamente. Los números negativos no tienen que contar el cero.
nevan king
1
"16 bits. En ese caso, int, es 2 bytes" puede ser incorrecto, si CHAR_BIT es 16, sizeof (int) puede ser 1 byte (o char).
12431234123412341234123
66
@nevanking: solo si asume la representación del complemento de 2 para firmado int. C no hace esa suposición. El complemento de 1 y los sistemas de magnitud de signo no pueden representar -32768en 16 bits; más bien, tienen dos representaciones para cero (positivo y negativo). Es por eso que el rango mínimo para un intes [-32767..32767].
John Bode
33

No hay una respuesta específica. Depende de la plataforma. Está definido por la implementación. Puede ser 2, 4 o algo más.

La idea detrás intera que se suponía que debía coincidir con el tamaño natural de "palabra" en la plataforma dada: 16 bits en plataformas de 16 bits, 32 bits en plataformas de 32 bits, 64 bits en plataformas de 64 bits, se entiende la idea. Sin embargo, para fines de compatibilidad con versiones anteriores, algunos compiladores prefieren mantener 32 bits intincluso en plataformas de 64 bits.

Sin intembargo, el tiempo de 2 bytes ya pasó (¿plataformas de 16 bits?) A menos que esté utilizando alguna plataforma integrada con un tamaño de palabra de 16 bits. Tus libros de texto son probablemente muy viejos.

Hormiga
fuente
2
The idea behind int was that it was supposed to match the natural "word" size on the given platform- Esto es lo que estaba buscando. ¿Alguna idea de cuál puede ser la razón? En un mundo libre, int podría ocupar cualquier número de bytes consecutivos en la memoria, ¿verdad? 8, 16 lo que sea
bholagabbar
19

La respuesta a esta pregunta depende de la plataforma que esté utilizando.
Pero independientemente de la plataforma, puede asumir de manera confiable los siguientes tipos:

 [8-bit] signed char: -127 to 127
 [8-bit] unsigned char: 0 to 255
 [16-bit]signed short: -32767 to 32767
 [16-bit]unsigned short: 0 to 65535
 [32-bit]signed long: -2147483647 to 2147483647
 [32-bit]unsigned long: 0 to 4294967295
 [64-bit]signed long long: -9223372036854775807 to 9223372036854775807
 [64-bit]unsigned long long: 0 to 18446744073709551615
Priyank Arora
fuente
3
Alguien editó su publicación para "arreglar" los rangos, pero no estoy seguro de si su edición refleja adecuadamente su intención. Asume la implementación del complemento de dos, lo cual será cierto en la mayoría de los casos, pero no en todos. Dado que su respuesta señala específicamente la dependencia de la implementación, creo que la edición probablemente sea incorrecta. Si está de acuerdo, asegúrese de revertir la edición.
Cody Gray
1
@ k06a su edición fue incorrecta . Ha cambiado específicamente los rangos originales en rangos de 2 complementos; estos no son los especificados en el estándar C.
Antti Haapala
@CodyGray esto ha estado fluctuando de un lado a otro, después de haber cumplido con el complemento de 1 durante los últimos 3 años y OP no dijo nada, así que revertí una edición que lo cambió al complemento de 2 con "rangos fijos", ya que dice "puede asumir de manera confiable" , que aún no es exactamente cierto.
Antti Haapala
13

¿Una variable entera en C ocupa 2 bytes o 4 bytes?

Eso depende de la plataforma que esté utilizando, así como de cómo esté configurado su compilador. La única respuesta autorizada es usar el sizeofoperador para ver qué tan grande es un número entero en su situación específica.


¿Cuáles son los factores de los que depende?

El rango puede ser mejor considerado, en lugar del tamaño . Ambos variarán en la práctica, aunque es mucho más infalible elegir tipos de variables por rango que por tamaño, como veremos. También es importante tener en cuenta que el estándar nos alienta a considerar elegir nuestros tipos enteros en función del rango en lugar del tamaño , pero por ahora ignoremos la práctica estándar y dejemos que nuestra curiosidad explore sizeof, bytes y CHAR_BIT, y la representación de enteros ... profundicemos la madriguera del conejo y verlo por nosotros mismos ...


sizeof, bytes y CHAR_BIT

La siguiente declaración, tomada del estándar C (vinculado a arriba), describe esto en palabras que no creo que puedan mejorarse.

El sizeofoperador produce el tamaño (en bytes) de su operando, que puede ser una expresión o el nombre entre paréntesis de un tipo. El tamaño se determina a partir del tipo de operando.

Asumir una comprensión clara nos llevará a una discusión sobre los bytes . Se supone comúnmente que un byte es de ocho bits, cuando en realidad CHAR_BITle dice cuántos bits hay en un byte . Ese es solo otro de esos matices que no se considera cuando se habla de los enteros de dos (o cuatro) bytes comunes .

Vamos a terminar las cosas hasta ahora:

  • sizeof => tamaño en bytes, y
  • CHAR_BIT => número de bits en byte

Por lo tanto, dependiendo de su sistema, sizeof (unsigned int)podría ser cualquier valor mayor que cero (no solo 2 o 4), como si fuera CHAR_BIT16, entonces un solo byte (dieciséis bits) tiene suficientes bits para representar el entero de dieciséis bits descrito por el normas (citadas a continuación). Esa no es necesariamente información útil, ¿verdad? Profundicemos más ...


Representación entera

El estándar C especifica la precisión / rango mínimo para todos los tipos enteros estándar (y CHAR_BIT, también, fwiw) aquí . A partir de esto, podemos derivar un mínimo de cuántos bits se requieren para almacenar el valor , pero también podemos elegir nuestras variables en función de los rangos . Sin embargo, una gran parte de los detalles necesarios para esta respuesta reside aquí. Por ejemplo, lo siguiente que el estándar unsigned intrequiere (al menos) dieciséis bits de almacenamiento:

UINT_MAX                                65535 // 2¹⁶ - 1

Por lo tanto, podemos ver que unsigned intrequieren ( al menos ) 16 bits , que es donde obtienes los dos bytes (suponiendo que CHAR_BITes 8) ... y más tarde cuando ese límite aumentó a 2³² - 1, las personas indicaron 4 bytes en su lugar. Esto explica los fenómenos que has observado:

La mayoría de los libros de texto dicen que las variables enteras ocupan 2 bytes. Pero cuando ejecuto un programa que imprime las direcciones sucesivas de una serie de enteros, muestra la diferencia de 4.

Estás utilizando un antiguo libro de texto y un compilador que te está enseñando C no portátil; el autor que escribió su libro de texto puede que ni siquiera lo sepa CHAR_BIT. Usted debe actualizar su libro de texto (y el compilador), y se esfuerzan por recordar que es un campo en constante evolución que se necesita para mantenerse por delante de la de competir ... basta de eso, sin embargo; veamos qué otros secretos no portátiles almacenan esos bytes enteros subyacentes ...

Los bits de valor son lo que parecen estar contando los conceptos erróneos comunes. El ejemplo anterior utiliza un unsignedtipo entero que generalmente contiene solo bits de valor, por lo que es fácil pasar por alto al diablo en los detalles.

Bits de signo ... En el ejemplo anterior, cité UINT_MAXcomo el límite superior unsigned intporque es un ejemplo trivial para extraer el valor 16del comentario. Para los tipos con signo, para distinguir entre valores positivos y negativos (ese es el signo), también debemos incluir el bit de signo.

INT_MIN                                -32768 // -(2¹⁵)
INT_MAX                                +32767 // 2¹⁵ - 1

Bits de relleno ... Si bien no es común encontrar computadoras que tienen bits de relleno en enteros, el estándar C permite que eso suceda; algunas máquinas (es decir, esta ) implementan tipos enteros más grandes combinando dos valores enteros más pequeños (con signo) juntos ... y cuando combina enteros con signo, obtiene un bit de signo perdido. Ese bit perdido se considera relleno en C. Otros ejemplos de bits de relleno pueden incluir bits de paridad y bits de captura .


Como puede ver, el estándar parece alentar la consideración de rangos como INT_MIN... INT_MAXy otros valores mínimos / máximos del estándar al elegir tipos enteros, y desaconseja depender de los tamaños, ya que hay otros factores sutiles que probablemente se olviden, como los CHAR_BITbits de relleno que podría afectar el valor de sizeof (int)(es decir, los conceptos erróneos comunes de los enteros de dos y cuatro bytes descuidan estos detalles).

Flimzy
fuente
13

C99 N1256 borrador estándar

http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf

El tamaño de inty todos los demás tipos enteros están definidos por la implementación, C99 solo especifica:

  • tamaño mínimo garantizado
  • tamaños relativos entre los tipos

5.2.4.2.1 "Tamaños de tipos enteros <limits.h>" da los tamaños mínimos:

1 [...] Sus valores definidos por la implementación serán iguales o mayores en magnitud (valor absoluto) a los mostrados [...]

  • UCHAR_MAX 255 // 2 8 - 1
  • USHRT_MAX 65535 // 2 16 - 1
  • UINT_MAX 65535 // 2 16 - 1
  • ULONG_MAX 4294967295 // 2 32 - 1
  • ULLONG_MAX 18446744073709551615 // 2 64-1

6.2.5 "Tipos" luego dice:

8 Para dos tipos enteros con el mismo signo y diferente rango de conversión de enteros (ver 6.3.1.1), el rango de valores del tipo con rango de conversión de enteros más pequeño es un subrango de los valores del otro tipo.

y 6.3.1.1 "Booleanos, caracteres y enteros" determina los rangos de conversión relativos:

1 Cada tipo entero tiene un rango de conversión entero definido de la siguiente manera:

  • El rango de long long int será mayor que el rango de long int, que será mayor que el rango de int, que será mayor que el rango de short int, que será mayor que el rango de caracteres firmados.
  • El rango de cualquier tipo entero sin signo será igual al rango del tipo entero con signo correspondiente, si lo hay.
  • Para todos los tipos enteros T1, T2 y T3, si T1 tiene un rango mayor que T2 y T2 tiene un rango mayor que T3, entonces T1 tiene un rango mayor que T3
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
fuente
8

Las únicas garantías son que chardebe tener al menos 8 bits de ancho, shorty intdebe tener al menos 16 bits de ancho, y longdebe tener al menos 32 bits de ancho, y que sizeof (char)<= sizeof (short)<= sizeof (int)<= sizeof (long)(lo mismo es cierto para las versiones sin signo de esos tipos )

int puede tener entre 16 y 64 bits de ancho, dependiendo de la plataforma.

John Bode
fuente
6

¿Es el tamaño de C "int" 2 bytes o 4 bytes?

La respuesta es "sí" / "no" / "tal vez" / "tal vez no".

El lenguaje de programación C especifica lo siguiente: la unidad direccionable más pequeña, conocida chary también llamada "byte" , tiene exactamente una CHAR_BITanchura de bits, donde CHAR_BITtiene al menos 8.

Entonces, un byte en C no es necesariamente un octeto , es decir, 8 bits. En el pasado, una de las primeras plataformas en ejecutar código C (y Unix) tenía 4 bytes int, pero en total inttenía 36 bits, ¡porque CHAR_BITera 9!

intse supone que es el tamaño entero natural para la plataforma que tiene un rango de al menos-32767 ... 32767 . Puede obtener el tamaño de intlos bytes de la plataforma con sizeof(int); Cuando multiplique este valor por CHAR_BIT, sabrá qué tan ancho es en bits.


Si bien las máquinas de 36 bits están en su mayoría muertas, todavía hay plataformas con bytes que no son de 8 bits. Justo ayer hubo una pregunta sobre una MCU de Texas Instruments con bytes de 16 bits , que tiene un compilador compatible con C99, C11.

En TMS320C28x parece que char, shorty intson todos de 16 bits de ancho, y por lo tanto un byte. long intes de 2 bytes y long long intes de 4 bytes. La belleza de C es que aún se puede escribir un programa eficiente para una plataforma como esta, ¡e incluso hacerlo de manera portátil!

Antti Haapala
fuente
"¡porque CHAR_BIT tenía 9!" - ¿Tenían una computación de 362880 bits en ese entonces? Impresionante.
Josh Desmond
5

Principalmente depende de la plataforma que esté utilizando. Depende del compilador al compilador. Actualmente, en la mayoría de los compiladores int es de 4 bytes . Si desea verificar qué está usando su compilador, puede usarlo sizeof(int).

main()
{
    printf("%d",sizeof(int));
    printf("%d",sizeof(short));
    printf("%d",sizeof(long));
}

Lo único que promete el compilador de c es que el tamaño de short debe ser igual o menor que int y el tamaño de long debe ser igual o mayor que int. Entonces, si el tamaño de int es 4, entonces el tamaño de short puede ser 2 o 4 pero no mayor que eso. Lo mismo es cierto por mucho tiempo e int. También dice que el tamaño de corto y largo no puede ser el mismo.

justpraveen
fuente
1
Usar %dpara un size_tparámetro es UB.
Paul R
3

Esto depende de la implementación, pero generalmente en x86 y otras arquitecturas populares como ARM ints toman 4 bytes. Siempre puede verificar en tiempo de compilación utilizando sizeof(int)o cualquier otro tipo que desee verificar.

Si desea asegurarse de usar un tipo de un tamaño específico, use los tipos en <stdint.h>

slartibartfast
fuente
2
#include <stdio.h>

int main(void) {
    printf("size of int: %d", (int)sizeof(int));
    return 0;
}

Esto devuelve 4, pero probablemente depende de la máquina.

las leyes
fuente
1

¿Es el tamaño de C "int" 2 bytes o 4 bytes?

¿Una variable entera en C ocupa 2 bytes o 4 bytes?

C permite que "bytes" sean algo más que 8 bits por "byte".

CHAR_BIT Número de bits para el objeto más pequeño que no es un campo de bits (byte) C11dr §5.2.4.2.1 1

Un valor de algo más que 8 es cada vez menos común. Para una portabilidad máxima, use en CHAR_BITlugar de 8. El tamaño de un inten bits en C es sizeof(int) * CHAR_BIT.

#include <limits.h>
printf("(int) Bit size %zu\n", sizeof(int) * CHAR_BIT);

¿Cuáles son los factores de los que depende?

El inttamaño de bit es comúnmente de 32 o 16 bits. C rangos mínimos especificados :

valor mínimo para un objeto de tipo int INT_MIN-32767
valor máximo para un objeto de tipo int INT_MAX32767
C11dr §5.2.4.2.1 1

El rango mínimo para intobliga a que el tamaño de los bits sea de al menos 16, incluso si el procesador era de "8 bits". Un tamaño como 64 bits se ve en procesadores especializados. Otros valores como 18, 24, 36, etc. han ocurrido en plataformas históricas o son al menos teóricamente posibles. La codificación moderna rara vez se preocupa por los inttamaños de 2 bits sin potencia .

El procesador y la arquitectura de la computadora controlan la intselección del tamaño de bits.

Sin embargo, incluso con procesadores de 64 bits, el inttamaño del compilador puede ser de 32 bits por razones de compatibilidad, ya que las bases de código grandes dependen de intser de 32 bits (o 32/16).

chux - Restablece a Monica
fuente
-1

Esta es una buena fuente para responder esta pregunta.

Pero esta pregunta es una especie de verdad siempre y fue "Sí. Ambas".

Depende de tu arquitectura. Si va a trabajar en una máquina de 16 bits o menos, no puede ser de 4 bytes (= 32 bits). Si está trabajando en una máquina de 32 bits o mejor, su longitud es de 32 bits.

Para averiguarlo, prepare su programa para generar algo legible y use la función "sizeof". Eso devuelve el tamaño en bytes de su tipo de datos declarado. Pero tenga cuidado al usar esto con matrices.

Si está declarando int t[12];, devolverá 12 * 4 bytes. Para obtener la longitud de esta matriz, solo use sizeof(t)/sizeof(t[0]). Si va a construir una función, que debería calcular el tamaño de una matriz de envío, recuerde que si

typedef int array[12];
int function(array t){
    int size_of_t = sizeof(t)/sizeof(t[0]);
    return size_of_t;
}
void main(){
    array t = {1,1,1};  //remember: t= [1,1,1,0,...,0]
    int a = function(t);    //remember: sending t is just a pointer and equal to int* t
   print(a);   // output will be 1, since t will be interpreted as an int itselve. 
}

Entonces esto ni siquiera devolverá algo diferente. Si define una matriz e intenta obtener la longitud después, use sizeof. Si envía una matriz a una función, recuerde que el valor de envío es solo un puntero en el primer elemento. Pero en el primer caso, siempre se sabe qué tamaño tiene su matriz. El caso dos se puede resolver definiendo dos funciones y perder algo de rendimiento. Defina la función (matriz t) y defina la función2 (matriz t, int size_of_t). Llame a "función (t)", mida la longitud mediante algún trabajo de copia y envíe el resultado a function2, donde puede hacer lo que quiera en tamaños de matriz variables.

Shalec
fuente
El enlace proporcionado es una mala fuente de información porque supone cosas que no siempre son ciertas (por ejemplo, charsiempre lo es signed)
Andrei Damian-Fekete