¿Por qué sizeof int es incorrecto, mientras que sizeof (int) es correcto?

96

Sabemos que sizeofes un operador que se usa para calcular el tamaño de cualquier tipo de datos y expresión, y cuando el operando es una expresión, se pueden omitir los paréntesis.

int main()
{
        int a;

        sizeof int;
        sizeof( int );
        sizeof a;
        sizeof( a );

        return 0;
}

el primer uso de sizeofes incorrecto, mientras que otros son correctos.

Cuando se compila usando gcc, aparecerá el siguiente mensaje de error:

main.c:5:9: error: expected expression before int

Mi pregunta es por qué el estándar C no permite este tipo de operación. ¿Causará sizeof intalguna ambigüedad?

Yishu Fang
fuente
5
Lo curioso es que no se aceptan todas las expresiones sin paréntesis: prueba sizeof (int)a.
Fred Foo
2
@MikkelK .: OP está preguntando un razonamiento detrás de las citas estándar; ya conoce las citas que se mencionan en la respuesta marcada.
Alok Save
2
@Lundin: sizeof +(int)atiene la ventaja *&de compilar realmente ;-)
Steve Jessop
2
@SteveJessop Ah, claro, no es un valor. Aunque se compiló en Embarcadero C ++, por extraño que parezca. De todos modos, creo que acabamos de encontrar un uso para el operador unario +. Debe ser la primera vez en la historia de la programación en C :)
Lundin
2
@Lundin: Aún hay que tener cuidado con unario +. Por ejemplo, sizeof +(char)a == sizeof(int)debido a la promoción de números enteros, es probable que sea menos propenso a errores solo poner entre paréntesis si hay alguna preocupación acerca de la expresión de la que está tratando de tomar el tamaño. Así que no estoy seguro de ir tan lejos como para llamarlo "un uso", aunque admito que lo usé ...
Steve Jessop

Respuestas:

101

Lo siguiente podría ser ambiguo:

sizeof int * + 1

¿Eso es (sizeof (int*)) + 1, o (sizeof(int)) * (+1)?

Obviamente, el lenguaje C podría haber introducido una regla para resolver la ambigüedad, pero puedo imaginar por qué no se molestó. Con el lenguaje tal como está, un especificador de tipo nunca aparece "desnudo" en una expresión, por lo que no hay necesidad de reglas para resolver si ese segundo *es parte del tipo o un operador aritmético.

La gramática existente ya resuelve la posible ambigüedad de sizeof (int *) + 1. Es (sizeof(int*))+1, no sizeof((int*)(+1)) .

C ++ tiene un problema similar que resolver con la sintaxis de conversión de estilo de función. Puedes escribir int(0)y puedes escribir typedef int *intptr; intptr(0);, pero no puedes escribir int*(0). En ese caso, la resolución es que el tipo "desnudo" debe ser un nombre de tipo simple, no puede ser cualquier ID de tipo antiguo que pueda tener espacios o puntuación final. Tal vez sizeofpodría haberse definido con la misma restricción, no estoy seguro.

Steve Jessop
fuente
1
C ++ tiene lo new int*(X)que sería ambiguo si C ++ no especificara que el nuevo operador toma la cadena más larga que posiblemente podría ser un tipo. Entonces en C ++ podrían haber hecho lo mismo con sizeof, supongo. Pero en C ++ se puede decir sizeof int()cuál habría sido ambiguo (¿tipo o valor inicializado int?).
Johannes Schaub - litb
@ JohannesSchaub-litb: Mmm, entonces quizás C ++ podría decir que se prefiere el tipo si es posible analizar uno, de lo contrario es una expresión. La ambigüedad se resolvería, pero sizeof int()estaría mal formada ("no operator()para size_t"), ¡lo cual espero que no sea bienvenido!
Steve Jessop
32

Desde C99 Standard

6.5.3.4.2
El sizeofoperador da el tamaño (en bytes) de su operando, que puede ser una expresión o el nombre entre paréntesis de un tipo.

En su caso, intno hay expresión ni nombre entre paréntesis.

Jainendra
fuente
10
No entiendo por qué esto obtiene 7 votos a favor. Al igual que las tres respuestas eliminadas, simplemente repite la regla en lugar de explicar por qué existe la regla.
Fred Foo
7
@larsmans, sí, estoy de acuerdo contigo. Aunque sigue repitiendo la regla, pero al menos, da una pieza de lectura autorizadora.
Yishu Fang
3
@larsmans Si empezamos a intentar justificar cada decisión tomada en C99, estaremos aquí todo el año. Citar el estándar es una forma tan buena como cualquier otra de concluir esta discusión.
Perry
1
@Perry: si no le gusta este tipo de pregunta, puede votar para cerrar la pregunta como argumentativa.
Fred Foo
4
Como no practicante de C ++, incluso yo entiendo esta respuesta, no estoy seguro de cuál es el problema si puedes leer y comprender inglés.
Kev
6

Hay dos formas de usar el operador sizeof en C. La sintaxis es la siguiente:

C11 6.5.3 Unary operators
...
sizeof unary-expression
sizeof ( type-name )

Siempre que use un tipo como operando, debe tener el paréntesis, por la definición de sintaxis del lenguaje. Si usa sizeof en una expresión, no necesita el paréntesis.

El estándar C da un ejemplo de dónde podría querer usarlo en una expresión:

sizeof array / sizeof array[0]

Sin embargo, en aras de la coherencia y para evitar errores relacionados con la precedencia del operador, personalmente recomendaría usar siempre () sin importar la situación.

Lundin
fuente
@ JohannesSchaub-litb Estoy de acuerdo en que no proporciona ningún fundamento sobre cómo razonó el comité del estándar C cuando especificó el estándar C90. Tendría que preguntarles ... Responde sin ningún fundamento proporcionado, sin embargo, C no lo permite ya que la sintaxis es como se especifica en 6.5.3. El OP tampoco parecía darse cuenta de la diferencia entre sizeof expressiony sizeof(type), que se explica en esta respuesta.
Lundin
(Para que conste, acabo de leer los fundamentos de C90 y C11 y ninguno proporciona ninguna explicación).
Lundin
Sospecho que no hay una justificación necesaria para ello, es simplemente la forma en que los diseñadores originales de C decidieron hacerlo. Tal vez facilitó las cosas para el analizador inicial. Iba a publicar una respuesta sobre el hecho de que typedefs y variables comparten el mismo espacio de nombres, pero eso no excluye permitir la primera sintaxis; solo necesita las reglas de análisis para decir que prefiere la variable cuando no hay paréntesis, prefiere el tipo cuando los hay, y cualquiera de las formas puede usarse cuando el nombre no es ambiguo. Como no es necesario cambiarlo, los comités de normas lo dejaron en paz.
Barmar