sprintf c types casting printf void-pointers

sprintf - scanf



El especificador de formato% p necesita conversión explícita a nula*para todos los tipos pero char*en printf (4)

He leído muchas respuestas sobre el uso del especificador de formato %p en lenguaje C aquí en Desbordamiento de pila, pero ninguna parece dar una explicación de por qué se necesita la void* explícita para void* para todos los tipos excepto char* .
Por supuesto, soy consciente del hecho de que este requisito para emitir desde o hacia el void* está relacionado con el uso de funciones variadic (ver el primer comentario de esta answer ), aunque no es obligatorio.

Aquí hay un ejemplo:

int i; printf ("%p", &i);

Muestra una advertencia sobre la incompatibilidad de tipos y que &i se debe void* (como lo exige la norma, ver de nuevo here ).

Mientras que este fragmento de código se compila sin problemas, sin ninguna queja sobre el tipo de casting en absoluto:

char * m = "Hello"; printf ("%p", m);

¿Cómo es que " char* " se "libera" de este imperativo?

PD : Tal vez vale la pena agregar que trabajo en la arquitectura x86_64 , ya que el tamaño del tipo de puntero depende de ella, y usar gcc como compilador en Linux con -W -Wall -std=c11 -pedantic opciones de compilación.


Desde el Estándar C # 6.2.5p28

Un puntero para anular debe tener los mismos requisitos de representación y alineación que un puntero a un tipo de carácter.48 De manera similar, los punteros a versiones calificadas o no calificadas de tipos compatibles deben tener los mismos requisitos de representación y alineación. Todos los punteros a los tipos de estructura deben tener los mismos requisitos de representación y alineación que los demás. Todos los indicadores de tipos de unión deben tener los mismos requisitos de representación y alineación que los demás. Los punteros a otros tipos no necesitan tener los mismos requisitos de representación o alineación. [énfasis mío]


El estándar C11 6.2.5 / 28 dice:

Un puntero a anular tendrá los mismos requisitos de representación y alineación que un puntero a un tipo de carácter. 48)

con la nota 48 siendo:

Los mismos requisitos de representación y alineación tienen el propósito de implicar intercambiabilidad como argumentos a funciones , valores de retorno de funciones y miembros de uniones.

Sin embargo, 7.21.6.1 ("La función fprintf") dice acerca de %p :

El argumento será un puntero a nulo.

Esto es aparentemente una contradicción. En mi opinión, una interpretación sensata es decir que la intención de 6.2.5 / 28 es que void * y char * son de hecho intercambiables como los tipos de argumentos de función que no corresponden a un prototipo. (es decir, argumentos a funciones no prototipadas, o que coinciden con los puntos suspensivos de un prototipo de función variadic).

Al parecer, el compilador que está utilizando tiene una vista similar.

Para respaldar esto, la especificación de los tipos de argumentos en 7.21.6.1, si se toma literalmente sin tener en cuenta la intención, tiene muchas otras inconsistencias que deben ser ignoradas en la práctica (por ejemplo, dice que printf("%lx", -1); está bien definido, pero printf("%u", 1); es un comportamiento indefinido).


El motivo de este requisito es que el Estándar C permite diferentes representaciones para punteros a diferentes tipos, con 2 restricciones notables:

Por lo tanto, en algunas arquitecturas, int * y char * pueden tener diferentes representaciones, por ejemplo, un tamaño diferente, y pueden pasarse de diferentes maneras a las funciones vararg, causando int i = 1; printf("%p", &i); int i = 1; printf("%p", &i); e int i = 1; printf("%p", (void*)&i); int i = 1; printf("%p", (void*)&i); comportarse de manera diferente.

Sin embargo, tenga en cuenta que los estándares de Posix obligan a que todos los tipos de punteros tengan el mismo tamaño y representación. Por lo tanto, en un sistema Posix printf("%p", &i); Debe comportarse como se espera.


No hay conversión explícita necesaria para argumentos de tipo char* , ya que char * tiene el mismo requisito de representación y alineación que void * .

Citando C11 , capítulo §6.2.5.

Un puntero a anular tendrá los mismos requisitos de representación y alineación que un puntero a un tipo de carácter. (48) [...]

y la nota 48)

Los mismos requisitos de representación y alineación tienen el propósito de implicar intercambiabilidad como argumentos a funciones, valores de retorno de funciones y miembros de uniones.