Los punteros no son enteros con signo, ya que se parecen mucho más a enteros sin signo. Sin embargo, los está imprimiendo como si fueran enteros con signo. En un sistema de 32 bits, hay varias cosas que probablemente tengan 32 bits de longitud: int
, unsigned int
, float
y punteros. En general, no se puede decir cuáles son simplemente mirándolos, pero todos significan cosas diferentes. (Como experimento, puede pasar varios enteros e imprimirlos como flotadores y viceversa: es una mala práctica en general, pero puede mostrarle que diferentes tipos de datos significan cosas diferentes.)
Funciones que toman un número variable de argumentos (funciones "variadic") lo hacen de una manera complicada. En particular, no verifican los tipos de argumentos. Puede pasar cualquier argumento que desee al printf()
y funciones similares, pero lograr que estén de acuerdo con el especificador de formato es su problema. Esto significa que la función no tiene forma de obtener el tipo correcto (como lo haría si pasara un float
a una función como int foo(int)
).
Pasar los tipos de argumentos incorrectos conduce a un comportamiento indefinido, y es particularmente probable que genere problemas si pasa argumentos del tamaño incorrecto. En la mayoría de los sistemas de 64 bits, los punteros son 64 bits y int
s son 32.
Por lo tanto, debe usar lo correcto en la cadena de formato. printf("%p", &a);
imprimirá la dirección de a
como un puntero, que es lo que desea. El estándar requiere algo como printf("%p", (void *)&a);
, pero como una cuestión práctica que es innecesaria en cualquier computadora es probable que encuentre.
'% 08x' es no portátil (y en realidad sería mal estado en una plataforma LLP64, por ejemplo) . –
Sí, es por eso que debe usar '% p', pero vale la pena mencionar que mucha gente usa'% 08x' en máquinas de 32 bits. El 99% del tiempo, si está imprimiendo un valor de puntero, está depurando algo, para que sepa exactamente en qué arquitectura se está ejecutando. –