Operador 'sizeof' con expresión condicional (ternaria)

Me cuesta entendersizeof's comportamiento cuando se le da una expresión ternaria.

#define STRING "a string"

int main(int argc, char** argv)
{
  int a = sizeof(argc > 1 ? STRING : "");

  int b = sizeof(STRING);
  int c = sizeof("");

  printf("%d\n" "%d\n" "%d\n", a, b, c);

  return 0;
}

En este ejemplo (probado con gcc 4.4.3 y 4.7.2, compilado con-std=c99), b es 9 (8 caracteres + implícito'\0'), c es 1 (implícito'\0') a, por alguna razón, es4.

Esperaría que a sea 9 o 1, en función de si argc es mayor que 1. Pensé que tal vez los literales de cadena se conviertan en punteros antes de pasarlos asizeof, causandosizeof(char*) ser 4.

Traté de reemplazarSTRING y"" por matrices de caracteres ...

char x[] = "";
char y[] = "a string";
int a = sizeof(argc > 1 ? x : y);

... pero obtuve los mismos resultados (a = 4, b = 9, c = 1).

Entonces traté de sumergirme en elEspecificación C99, pero no encontré ninguna explicación obvia en él. Por curiosidad también intenté cambiar el cambio de xey a otros tipos:

char ylong long int: a se convierte en 8ambosshort o amboschar: a se convierte en 4

Así que definitivamente está ocurriendo algún tipo de conversión, pero me cuesta encontrar alguna explicación oficial. Puedo imaginar que esto sucedería con los tipos aritméticos (estoy vagamente consciente de que hay muchas promociones cuando están involucradas), pero no veo por quéuna cadena literal devuelta por una expresión ternaria se convertiría en algo de tamaño 4.

NB: en esta máquinasizeof(int) == sizeof(foo*) == 4.

Seguimiento

Gracias por los punteros chicos. Comprender cómosizeof y?: El trabajo en realidad me llevó a probar algunos mashups de tipos más y ver cómo reaccionó el compilador. Los estoy editando por completo:

foo* x = NULL; /* or foo x[] = {} */
int  y = 0;    /* or any integer type */

int a = sizeof(argc > 1 ? x : y);

Rendimientoswarning: pointer/integer type mismatch in conditional expression [enabled by default]ya == sizeof(foo*).

Confoo x[], bar y[], foo* x, bar* y ofoo* x, bar y[], la advertencia se conviertepointer type mismatch. No hay advertencia al usar unvoid*.

float x = 0; /* or any floating-point type */
int   y = 0; /* or any integer type */

int a = sizeof(argc > 1 ? x : y);

No produce ninguna advertencia, ya == sizeof(x) (es decir, el tipo de punto flotante).

float x = 0;    /* or any floating-point type */
foo*  y = NULL; /* or foo y[] = {} */

int a = sizeof(argc > 1 ? x : y);

Rendimientoserror: type mismatch in conditional expression.

Si alguna vez leo la especificación por completo, me aseguraré de editar esta pregunta para señalar las partes relevantes.

Respuestas a la pregunta(3)

Su respuesta a la pregunta