tipos sirve rangos que para funcion float datos codigo c assembly types

sirve - "Los tamaños de tipo variable C dependen de la máquina." ¿Es realmente cierto? números firmados y sin firmar;



unsigned char c (6)

¿Qué significa exactamente "Los tipos de variables dependen de la máquina?"

Significa exactamente lo que dice: los tamaños de la mayoría de los tipos de C integrales dependen de la máquina (en realidad no son tanto máquinas como arquitectura y compilador). Cuando estaba haciendo mucho C a principios de los 90, int era en su mayoría de 16 bits; ahora es en su mayoría de 32 bits. Antes de mi carrera en C, puede haber sido de 8 bits. Etc.

Aparentemente, los diseñadores del compilador de C que está utilizando para la compilación de 64 bits decidieron que int debería permanecer en 32 bits. Los diseñadores de un compilador C diferente pueden hacer una elección diferente.

Me han dicho que los tipos C dependen de la máquina. Hoy quería verificarlo.

void legacyTypes() { /* character types */ char k_char = ''a''; //Signedness --> signed & unsigned signed char k_char_s = ''a''; unsigned char k_char_u = ''a''; /* integer types */ int k_int = 1; /* Same as "signed int" */ //Signedness --> signed & unsigned signed int k_int_s = -2; unsigned int k_int_u = 3; //Size --> short, _____, long, long long short int k_s_int = 4; long int k_l_int = 5; long long int k_ll_int = 6; /* real number types */ float k_float = 7; double k_double = 8; }

Lo compilé en una máquina de 32 bits usando el compilador minGW C

_legacyTypes: pushl %ebp movl %esp, %ebp subl $48, %esp movb $97, -1(%ebp) # char movb $97, -2(%ebp) # signed char movb $97, -3(%ebp) # unsigned char movl $1, -8(%ebp) # int movl $-2, -12(%ebp)# signed int movl $3, -16(%ebp) # unsigned int movw $4, -18(%ebp) # short int movl $5, -24(%ebp) # long int movl $6, -32(%ebp) # long long int movl $0, -28(%ebp) movl $0x40e00000, %eax movl %eax, -36(%ebp) fldl LC2 fstpl -48(%ebp) leave ret

Recopilé el mismo código en el procesador de 64 bits (Intel Core 2 Duo) en GCC (Linux)

legacyTypes: .LFB2: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 movq %rsp, %rbp .cfi_offset 6, -16 .cfi_def_cfa_register 6 movb $97, -1(%rbp) # char movb $97, -2(%rbp) # signed char movb $97, -3(%rbp) # unsigned char movl $1, -12(%rbp) # int movl $-2, -16(%rbp)# signed int movl $3, -20(%rbp) # unsigned int movw $4, -6(%rbp) # short int movq $5, -32(%rbp) # long int movq $6, -40(%rbp) # long long int movl $0x40e00000, %eax movl %eax, -24(%rbp) movabsq $4620693217682128896, %rax movq %rax, -48(%rbp) leave ret

Observaciones

  • char, signed char, unsigned char, int, unsigned int, signed int, short int, unsigned short int, signed short int todos ocupan el mismo no. de bytes en el procesador de 32 bits y 64 bits.

  • El único cambio es en long int y long long int ambos ocupan 32 bits en máquina de 32 bits y 64 bits en máquina de 64 bits.

  • Y también los punteros, que toman 32 bits en CPU de 32 bits y 64 bits en CPU de 64 bits.

Preguntas:

  • No puedo decir lo que los libros dicen que está mal. Pero me falta algo aquí. ¿Qué significa exactamente "Los tipos de variables dependen de la máquina?"
  • Como puede ver, no hay diferencia entre las instrucciones para los números sin firmar y los firmados. Entonces, ¿cómo es que el rango de números que se pueden abordar con ambos es diferente?
  • Estaba leyendo ¿Cómo mantener el tamaño fijo de los tipos de variables C en diferentes máquinas? No entendí el propósito de la pregunta ni sus respuestas. ¿Qué mantener un tamaño fijo? Todos son iguales. No entendí cómo esas respuestas garantizarán el mismo tamaño.

EDITAR:

¿No es imposible proporcionar el mismo tamaño en diferentes máquinas? Quiero decir, ¿cómo se puede mantener el mismo tamaño de puntero tanto en la máquina de 64 bits como en la de 32 bits?


¡Hay muchas más plataformas, y algunas tienen 16 o incluso 8 bits! En estos, observaría diferencias mucho mayores en los tamaños de todos los tipos anteriores.

Las versiones firmadas y no firmadas del mismo tipo básico ocupan el mismo número de bytes en cualquier plataforma, sin embargo, su rango de números es diferente ya que para un número firmado se comparte el mismo rango de valores posibles entre el dominio firmado y el no firmado.

Por ejemplo, un int. Firmado de 16 bits puede tener valores de -32767 (o -32768 en muchas plataformas) a 32767. Un int sin signo del mismo tamaño está en el rango de 0 a 65535.

Después de esto, espero que entiendas mejor el punto de la pregunta referida. Básicamente, si escribe un programa suponiendo que, por ejemplo, sus variables int firmadas podrán contener el valor 2 * 10 ^ 9 (2 mil millones), su programa no es portátil, porque en algunas plataformas (16 bits o menos) este valor causará un desbordamiento, lo que genera errores silenciosos y difíciles de encontrar. Así que, por ejemplo, en una plataforma de 16 bits, debe #define definir que sus entradas sean long para evitar el desbordamiento. Este es un ejemplo simple, que puede no funcionar en todas las plataformas, pero espero que te dé una idea básica.

La razón de todas estas diferencias entre plataformas es que para cuando C se estandarizó, ya había muchos compiladores de C utilizados en una gran cantidad de plataformas diferentes, por lo que para compatibilidad con versiones anteriores, todas estas variedades tenían que ser aceptadas como válidas.


Aquí hay algo más que otra implementación, bastante diferente de lo que está acostumbrado, pero que todavía está presente en Internet hoy en día, incluso si ya no se usa para computación de propósito general, exceptuando los aficionados a la informática retroactiva. Ninguno de los tamaños son los mismos que los tuyos:

@type sizes.c #include <stdio.h> #include <limits.h> int main() { printf("CHAR_BIT = %d/n", CHAR_BIT); printf("sizeof(char) = %d/n", sizeof(char)); printf("sizeof(short) = %d/n", sizeof(short)); printf("sizeof(int) = %d/n", sizeof(int)); printf("sizeof(long) = %d/n", sizeof(long)); printf("sizeof(float) = %d/n", sizeof(float)); printf("sizeof(double) = %d/n", sizeof(double)); return 0; } @run sizes.exe CHAR_BIT = 9 sizeof(char) = 1 sizeof(short) = 2 sizeof(int) = 4 sizeof(long) = 4 sizeof(float) = 4 sizeof(double) = 8


Los compiladores reales usualmente no aprovechan todas las variaciones permitidas por el estándar. Los requisitos en el estándar solo dan un rango mínimo para el tipo: 8 bits para char, 16 bits para short e int, 32 bits para long, y (en C99) 64 bits para long long (y cada tipo en esa lista debe tener al menos un rango tan grande como el tipo anterior).

Para un compilador real, sin embargo, la compatibilidad con versiones anteriores es casi siempre un objetivo principal. Eso significa que tienen una fuerte motivación para cambiar tan poco como pueden salirse con la suya. Como resultado, en la práctica, hay mucho más en común entre los compiladores de lo que exige el estándar.


Si repitiera su prueba en, digamos, un procesador Motorola 68000, encontraría resultados diferentes (con una palabra de 16 bits y una larga de 32, típicamente una int es una palabra)


La máquina dependiente no es exactamente exacta. En realidad, está definido por la implementación . Puede depender de compilador, máquina, opciones de compilación, etc.

Por ejemplo, usando Visual C ++, long sería 32 bit incluso en máquinas de 64 bits.