La diferencia real entre “int” y “unsigned int”

int :

El tipo de datos int de 32 bits puede contener valores enteros en el rango de −2,147,483,648 a 2,147,483,647. También puede referirse a este tipo de datos como firmado o firmado.

unsigned int :

El tipo de datos int sin signo de 32 bits puede contener valores enteros en el rango de 0 a 4,294,967,295. También puede referirse a este tipo de datos simplemente como sin firmar.

Ok, pero, en la práctica:

int x = 0xFFFFFFFF; unsigned int y = 0xFFFFFFFF; printf("%d, %d, %u, %u", x, y, x, y); // -1, -1, 4294967295, 4294967295 

No hay diferencia, Oo estoy un poco confundido.

Jeje Tiene un elenco implícito aquí, porque le está diciendo a printf qué tipo de expectativa.

Prueba esto para el tamaño en su lugar:

 unsigned int x = 0xFFFFFFFF; int y = 0xFFFFFFFF; if (x < 0) printf("one\n"); else printf("two\n"); if (y < 0) printf("three\n"); else printf("four\n"); 

Sí, porque en tu caso usan la misma representación .

El patrón de bits 0xFFFFFFFF parece a -1 cuando se interpreta como un entero con signo de 32b y como 4294967295 cuando se interpreta como un entero sin signo de 32b.

Es lo mismo que char c = 65 . Si lo interpretas como un entero con signo, es 65. Si lo interpretas como un carácter, es a .


Como señalan R y pmg, técnicamente es un comportamiento indefinido pasar argumentos que no coinciden con los especificadores de formato. Así que el progtwig podría hacer cualquier cosa (desde la impresión de valores aleatorios hasta el locking, la impresión de la cosa “correcta”, etc.).

El estándar lo señala en 7.19.6.1-9

Si una especificación de conversión no es válida, el comportamiento no está definido. Si algún argumento no es el tipo correcto para la especi fi cación de conversión correspondiente, el comportamiento no está definido.

No hay diferencia entre los dos en la forma en que se almacenan en la memoria y en los registros, no hay una versión firmada y sin firma de los registros int. No hay información firmada almacenada en el int. La diferencia solo se vuelve relevante cuando se realizan operaciones matemáticas. La versión firmada y sin firmar de las operaciones matemáticas integradas en la CPU y la firma le indican al comstackdor qué versión usar.

El problema es que invocaste un comportamiento indefinido .


Cuando invocas UB cualquier cosa puede pasar.

Las tareas están bien; Hay una conversión implícita en la primera línea.

 int x = 0xFFFFFFFF; unsigned int y = 0xFFFFFFFF; 

Sin embargo, la llamada a printf , no está bien.

 printf("%d, %d, %u, %u", x, y, x, y); 

Es UB no coincidir con el especificador % y el tipo del argumento.
En su caso, especifique 2 int sy 2 unsigned int s en este orden proporcionando 1 int , 1 unsigned int , 1 int y 1 unsigned int .


¡No hagas UB !

La representación interna de int y unsigned int es la misma.

Por lo tanto, cuando pase la misma cadena de formato a printf , se imprimirá igual.

Sin embargo, hay diferencias cuando las comparas. Considerar:

 int x = 0x7FFFFFFF; int y = 0xFFFFFFFF; x < y // false x > y // true (unsigned int) x < (unsigned int y) // true (unsigned int) x > (unsigned int y) // false 

Esto también puede ser una advertencia, ya que al comparar enteros con signo y sin signo, uno de ellos se convertirá implícitamente para que coincida con los tipos.

Él está preguntando acerca de la diferencia real . Cuando se habla de un comportamiento indefinido, se encuentra en el nivel de garantía que proporciona la especificación del idioma: está lejos de la realidad. Para comprender la diferencia real, compruebe este fragmento (por supuesto, esto es UB pero está perfectamente definido en su comstackdor favorito):

 #include  int main() { int i1 = ~0; int i2 = i1 >> 1; unsigned u1 = ~0; unsigned u2 = u1 >> 1; printf("int : %X -> %X\n", i1, i2); printf("unsigned int: %X -> %X\n", u1, u2); } 

el tipo simplemente te dice lo que se supone que representa el patrón de bits. Los bits son solo lo que ustedes hacen de ellos. Las mismas secuencias se pueden interpretar de diferentes maneras.

La función printf interpreta el valor que le pasa según el especificador de formato en una posición coincidente. Si le dice a printf que pasa un int , pero pasa unsigned lugar, printf volvería a interpretar uno como el otro e imprimirá los resultados que vea.

Este es bastante sencillo. La representación binaria es la clave que se menciona pero nunca se muestra. Sin firmar en HEX si 0XFFFFFFF = código de máquina = 1111 1111 1111 1111 1111 1111 1111 1111 = 4,294,967,295 representaciones positivas de un número. Todo eso está bien y es excelente, pero necesitamos una forma de representar números negativos. Así que los cerebros decidieron en dos complementos. ¿Qué significa esto? Bueno, en resumen, tomaron el dígito más a la izquierda y decidieron que cuando es un 1 (seguido de todos hasta llegar al bit más significativo a la izquierda) el número será negativo si es 0, es positivo. Ahora veamos lo que sucede 0000 0000 0000 0000 0000 0000 0000 0011 = 3 . Ahora continuemos agregando a este número 0111 1111 1111 1111 1111 1111 1111 1111 = 2,147,483,645 el número positivo más alto con un int firmado. Agreguemos 1 (aquí es posible que desee buscar una adición binaria) debemos llevar el uno por completo. 1111 1111 1111 1111 1111 1111 1111 1110 = -1 Entonces, en resumen, podemos decir que la diferencia es que uno permite los números negativos que el otro no, lo que se debe al bit de signo o al bit más a la izquierda o al bit más significativo.