¿Especificador de formato correcto para imprimir puntero o dirección?

5 minutos de lectura

avatar de usuario
San

¿Qué especificador de formato debo usar para imprimir la dirección de una variable? Estoy confundido entre el lote a continuación.

%u – entero sin signo

%x – valor hexadecimal

%p – puntero vacío

¿Cuál sería el formato óptimo para imprimir una dirección?

p es el especificador de conversión para imprimir punteros. Utilizar esta.

int a = 42;

printf("%p\n", (void *) &a);

Recuerde que omitir el molde es un comportamiento indefinido y que imprimir con p El especificador de conversión se realiza de una manera definida por la implementación.

  • Perdón, ¿por qué omitir el elenco es un “comportamiento indefinido”? ¿Importa la dirección de qué variable es, si todo lo que necesita es la dirección, no el valor?

    – valdo

    29 de enero de 2012 a las 13:54

  • @valdo porque C lo dice (C99, 7.19.6.1p8) “p El argumento será un puntero a void”.

    – ouah

    29 de enero de 2012 a las 13:55

  • @valdo: No es necesariamente el caso de que todos los punteros tengan el mismo tamaño/representación.

    – café

    29 de enero de 2012 a las 14:06

  • Bienvenido a SO. Tómese un tiempo para revisar las otras respuestas, explican claramente una serie de detalles que está pasando por alto.

    – AntoineL

    18 de febrero de 2020 a las 19:35

avatar de usuario
Kerrek SB

Usar %p, para “puntero”, y no use nada más*. El estándar no garantiza que pueda tratar un puntero como cualquier tipo particular de entero, por lo que en realidad obtendrá un comportamiento indefinido con los formatos integrales. (Por ejemplo, %u espera un unsigned intpero que si void* tiene un tamaño diferente o un requisito de alineación que unsigned int?)

*) [See Jonathan’s fine answer!] Alternativamente a %pusted puede utilizar macros específicas de puntero de <inttypes.h>añadido en C99.

Todos los punteros a objetos son implícitamente convertibles a void* en C, pero para pasar el puntero como un argumento variable, debe convertirlo explícitamente (ya que los punteros de objetos arbitrarios solo son convertiblepero no idéntico para anular punteros):

printf("x lives at %p.\n", (void*)&x);

  • Todos objeto Los punteros son convertibles a void * (aunque para printf() técnicamente necesitas el reparto explícito, ya que es una función variádica). Los punteros de función no son necesariamente convertibles a void *.

    – café

    29 de enero de 2012 a las 13:54

  • @caf: Oh, no sabía sobre los argumentos variados, ¡arreglado! ¡Gracias!

    – KerrekSB

    29 de enero de 2012 a las 13:58

  • El estándar C no requiere que los punteros de función sean convertibles a void * y volver al puntero de función sin pérdida; afortunadamente, sin embargo, POSIX lo requiere explícitamente (observando que no es parte del estándar C). Entonces, en la práctica, puede salirse con la suya (convirtiendo void (*function)(void) para void * y de vuelta a void (*function)(void)), pero estrictamente no lo exige el estándar C.

    –Jonathan Leffler

    29 de enero de 2012 a las 14:18

  • Jonathan y R.: Todo esto es muy interesante, pero estoy bastante seguro de que no estamos tratando de imprimir punteros de función aquí, así que tal vez este no sea el lugar adecuado para discutir esto. Preferiría mucho más ver algo de apoyo aquí por mi insistencia en no usar %u!

    – KerrekSB

    29 de enero de 2012 a las 16:08


  • %u y %lu están equivocados en todas las maquinas, no algunas máquinas. La especificación de printf Es muy claro que cuando el tipo pasado no coincide con el tipo requerido por el especificador de formato, el comportamiento es indefinido. Si el tamaño de los tipos coincide (que podría ser verdadero o falso, según la máquina) es irrelevante; son los tipos los que deben coincidir, y nunca lo harán.

    – R.. GitHub DEJA DE AYUDAR A ICE

    29 de enero de 2012 a las 18:09

avatar de usuario
R.. GitHub DEJAR DE AYUDAR A ICE

Como alternativa a las otras (muy buenas) respuestas, podría enviar a uintptr_t o intptr_t (desde stdint.h/inttypes.h) y utilice los especificadores de conversión de enteros correspondientes. Esto permitiría una mayor flexibilidad en la forma en que se formatea el puntero, pero estrictamente hablando, no se requiere una implementación para proporcionar estos typedefs.

  • Todos objeto Los punteros son convertibles a void * (aunque para printf() técnicamente necesitas el reparto explícito, ya que es una función variádica). Los punteros de función no son necesariamente convertibles a void *.

    – café

    29 de enero de 2012 a las 13:54

  • @caf: Oh, no sabía sobre los argumentos variados, ¡arreglado! ¡Gracias!

    – KerrekSB

    29 de enero de 2012 a las 13:58

  • El estándar C no requiere que los punteros de función sean convertibles a void * y volver al puntero de función sin pérdida; afortunadamente, sin embargo, POSIX lo requiere explícitamente (observando que no es parte del estándar C). Entonces, en la práctica, puede salirse con la suya (convirtiendo void (*function)(void) para void * y de vuelta a void (*function)(void)), pero estrictamente no lo exige el estándar C.

    –Jonathan Leffler

    29 de enero de 2012 a las 14:18

  • Jonathan y R.: Todo esto es muy interesante, pero estoy bastante seguro de que no estamos tratando de imprimir punteros de función aquí, así que tal vez este no sea el lugar adecuado para discutir esto. Preferiría mucho más ver algo de apoyo aquí por mi insistencia en no usar %u!

    – KerrekSB

    29 de enero de 2012 a las 16:08


  • %u y %lu están equivocados en todas las maquinas, no algunas máquinas. La especificación de printf Es muy claro que cuando el tipo pasado no coincide con el tipo requerido por el especificador de formato, el comportamiento es indefinido. Si el tamaño de los tipos coincide (que podría ser verdadero o falso, según la máquina) es irrelevante; son los tipos los que deben coincidir, y nunca lo harán.

    – R.. GitHub DEJA DE AYUDAR A ICE

    29 de enero de 2012 a las 18:09

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad