¿Por qué printf se comporta de manera diferente cuando intentamos imprimir caracteres como un flotador y como un hexadecimal?

Intenté imprimir caracteres como un flotante en printf y obtuve una salida 0. ¿Cuál es la razón de esto?
También:

char c='z'; printf("%f %X",c,c); 

está dando una salida extraña para hexadecimal mientras que la salida es correcta cuando hago esto:

 printf("%X",c); 

¿por que es esto entonces?

La printf() es una función variable , lo que significa que puede pasarle un número variable de argumentos de tipos no especificados. Esto también significa que el comstackdor no sabe qué tipo de argumentos espera la función, por lo que no puede convertir los argumentos a los tipos correctos. (Los comstackdores modernos pueden avisarte si obtienes los argumentos incorrectos para printf , si lo invocas con suficientes banderas de advertencia).

Por razones históricas, no puede pasar un argumento entero de rango más pequeño que int , o un tipo flotante de rango más pequeño que el double a una función variable. Un float se convertirá a double y un char se convertirá a int (o unsigned int en implementaciones extrañas) a través de un proceso denominado promociones de argumentos predeterminados .

Cuando printf analiza sus parámetros (los argumentos se pasan a una función, los parámetros son los que recibe la función), los recupera utilizando el método que sea apropiado para el tipo especificado por la cadena de formato. El especificador "%f" espera un double . El especificador "%X" espera un unsigned int .

Si pasa un int e printf intenta recuperar un double , invoca un comportamiento indefinido .
Si pasa un int e printf intenta recuperar un unsigned int , invoca un comportamiento indefinido .

El comportamiento indefinido puede incluir (pero no se limita a) imprimir valores extraños, bloquear su progtwig o (el más insidioso de todos) hacer exactamente lo que espera.

Fuente: n1570 (El borrador público final de la norma C actual)

Necesitas usar un operador de reparto como este:

 char c = 'z'; printf("%f %X", (float)c, c); 

o

 printf("%f %X", (double)c, c); 

En Xcode, si no hago esto, recibo la advertencia:

El formato especifica especifica ‘double’ pero el argumento tiene el tipo ‘char’, y la salida es 0.000000.

Intenté imprimir caracteres como un flotador en printf y obtuve una salida 0. ¿Cuál es la razón de esto?

La pregunta es, ¿qué valor esperabas ver? ¿Por qué esperarías algo más que 0?

La respuesta corta a su pregunta es que el comportamiento de printf no está definido si el tipo de argumento no coincide con el especificador de conversión. El especificador de conversión %f espera que su argumento correspondiente tenga double tipo; si no lo es, todas las apuestas están desactivadas y la salida exacta variará.

Para comprender el problema del punto flotante, considere leer: http://en.wikipedia.org/wiki/IEEE_floating_point

En cuanto al hexadecimal, déjame adivinar … la salida fue algo así como … ¿99?

Esto se debe a las codificaciones … la máquina tiene que representar información en algún formato, y generalmente ese formato implica dar significados a ciertos bits en un número, o tener una tabla de símbolos a números, o ambos

Los puntos flotantes a veces se representan como un triplete (signo, mantisa, exponente) todo en un número de 32 o 64 bits; los caracteres a veces se representan en un formato llamado ASCII, que establece qué número corresponde a cada carácter que usted escribe

Debido a que printf, como cualquier función que trabaja con varargs, por ejemplo: int foobar(const char fmt, ...) {} intenta interpretar su parámetro en cierto tipo.

Si dices "%f" , luego pasa c (como un char ), entonces printf intentará leer un float .

Puedes leer más aquí: var_arg (incluso si esto es C ++, todavía se aplica).