2011-03-06 10 views
11

Estoy leyendo un libro C. Para imprimir una dirección de memoria de una variable, a veces, el libro utiliza:¿diferencia entre imprimir una dirección de memoria usando% u y% d en C?

printf("%u\n",&n); 

A veces, el autor escribió:

printf("%d\n",&n); 

El resultado es siempre el mismo, pero no entiendo las diferencias entre los dos (sé% u para unsigned).

¿Alguien puede dar más detalles sobre esto, por favor?

Muchas gracias.

+1

Usaría 'printf ("% x \ n ", & n)' para imprimir la representación hexadecimal de la dirección. Pero solo soy yo. – dappawit

+6

Tire el libro lejos: nunca debe usar ni '% u' ni'% d' para imprimir direcciones, ya que una dirección puede tener más bits que un int - use '% p', o falla ese'% # llx'. –

+1

También debe convertir la dirección para que coincida con el tipo de especificador que elija. 'printf' no puede hacer conversiones automáticas ya que los argumentos no tienen parámetros de prototipos. Con '% p' que es' (void *) ', y con'% # llx' que es '(unsigned long long)', etc. –

Respuesta

36

%u trata el entero como sin signo, mientras que %d trata el entero como firmado. Si el número entero está entre 0 y INT_MAX (que es 2 -1 en sistemas de 32 bits), la salida es idéntica para ambos casos.

que sólo tiene una diferencia si el entero es negativo (para entradas firmados) o entre INT_MAX+1 y UINT_MAX (por ejemplo entre 2 y 2 -1). En ese caso, si usa el especificador %d, obtendrá un número negativo, mientras que si usa %u, obtendrá un número positivo grande.

Las direcciones solo tienen sentido como números sin firmar, por lo que nunca hay motivo para imprimirlas como números con signo. Además, cuando se imprimen, generalmente se imprimen en hexadecimal (con el especificador de formato %x), no en formato decimal.

En realidad, debería utilizar el especificador de formato %p para las direcciones; está garantizado que funciona para todos los punteros válidos. Si está en un sistema con enteros de 32 bits pero de 64 bits, si intenta imprimir un puntero con cualquiera de %d, %u o %x sin el modificador de longitud ll, obtendrá el resultado incorrecto para eso y cualquier otra cosa que se imprima más tarde (porque printf solo leyó 4 de los 8 bytes del argumento del puntero); si agrega el modificador de longitud ll, entonces no será portátil para los sistemas de 32 bits.

En pocas palabras: siempre use %p para la impresión de punteros/direcciones:

printf("The address of n is: %p\n", &n); 
// Output (32-bit system): "The address of n is: 0xbffff9ec" 
// Output (64-bit system): "The address of n is: 0x7fff5fbff96c" 

El formato exacto de salida es definido por la implementación (C99 §7.19.6.1/8), pero casi siempre se imprime como un número hexadecimal sin signo, generalmente con un 0x principal.

+0

muy bien explicado. ¿Podría dar una línea, por ejemplo, de cómo? para usar el especificador de formato% p – Algorithmist

+2

En C99 también hay varias macros definidas en 'inttypes.h' que le dan más flexibilidad al imprimir punteros.'% p' siempre imprime una dirección hexadecimal. Pero suponga que desea imprimirla en decimal (u octal!). 'printf (" Decimal:% "PRIuPTR", Octal:% "PRIo PTR "\ n", (uintptr_t) p, (uintptr_t) p); ' – rlibby

+0

Es posible que el libro C se haya escrito antes de agregar% p a la lib. –

1

%d y %u imprimirá los mismos resultados cuando el bit más significativo no esté configurado. Sin embargo, este no es un código portátil en absoluto, y no es un buen estilo. Espero que tu libro sea mejor de lo que parece en este ejemplo.

+0

En realidad, el libro debería decirle a él/ella que use 'printf (" % p \ n ", (vid *) &n);' – GWW

+0

podría por favor sugerir algún buen libro en C. – Algorithmist

+0

Lo aprendí de Kernighan & Ritchie, pero eso es probablemente un poco viejo para niños en estos días. –

0

¿Qué valor has probado? La diferencia sin signo vs. firmado, tal como dijiste que sabes. Entonces, ¿qué hizo y qué esperabas?

Los valores con signo positivo tienen el mismo aspecto que los no firmados, así que ¿puedo suponer que utilizó un valor menor para probar? ¿Qué tal un valor negativo?

Finalmente, si está intentando imprimir la dirección de la variable (como parece que está), use% p en su lugar.

0

Todas las direcciones no tienen signo de 32 bits o 64 bits, dependiendo de la máquina (no se puede escribir en una dirección negativa). El uso de% d no es apropiado, pero generalmente funcionará. Se recomienda usar% u o% ul.

Cuestiones relacionadas