sintaxis array c sizeof

c - array - sizeof string



¿Por qué sizeof(my_arr)[0] compila e igual sizeof(my_arr[0])? (4)

¿Por qué se compila este código?

_Static uint32_t my_arr[2]; _Static_assert(sizeof(my_arr) == 8, ""); _Static_assert(sizeof(my_arr[0]) == 4, ""); _Static_assert(sizeof(my_arr)[0] == 4, "");

Las primeras 2 afirmaciones son obviamente correctas, pero hubiera esperado que la última línea fallara, ya que entiendo que sizeof() debería evaluar a un literal entero, que no puede tratarse como una matriz. En otras palabras, fallaría de la misma manera que falla la siguiente línea:

_Static_assert(4[0] == 4, "");

Curiosamente, lo siguiente no puede compilarse (que debería estar haciendo lo mismo, ¿no?):

_Static_assert(*sizeof(my_arr) == 4, "");

error: argumento de tipo no válido de ''*'' unario (tiene ''int largo sin signo'') _Static_assert (* sizeof (my_arr) == 4, "");

Si importa, estoy usando gcc 5.3.0


Está utilizando la versión del operador sizeof que toma una expresión como parámetro. A diferencia del que toma un tipo, no requiere paréntesis. Por lo tanto, el operando es simplemente (my_arr)[0] , y los paréntesis son redundantes.


[] tienen mayor precedencia que sizeof . Entonces sizeof(my_arr)[0] es lo mismo que sizeof((my_arr)[0]) .

Here hay un enlace a una tabla de precedencia.


sizeof no es una función. Es un operador unario como ! o ~ .

sizeof(my_arr)[0] analiza como sizeof (my_arr)[0] , que es simplemente sizeof my_arr[0] con paréntesis redundantes.

Esto es igual que !(my_arr)[0] analiza como !(my_arr[0]) .

En general, los operadores de postfix tienen mayor prioridad que los operadores de prefijo en C. sizeof *a[i]++ analiza como sizeof (*((a[i])++)) (los operadores de postfix [] y ++ se aplican a primero, luego los operadores de prefijo * y sizeof ).

(Esta es la versión de expresión de sizeof . También hay una versión de tipo, que toma un nombre de tipo entre paréntesis: sizeof (TYPE) . En ese caso, se requerirían los padres y parte de la sintaxis de sizeof ).


sizeof tiene dos "versiones": sizeof(type name) y sizeof expression . El primero requiere un par de () alrededor de su argumento. Pero el último, el que tiene una expresión como argumento, no tiene () alrededor de su argumento. Cualquier cosa () que use en el argumento se ve como parte de la expresión del argumento, no como parte de la sintaxis del mismo sizeof .

Dado que el compilador conoce my_arr como un nombre de objeto, no como un nombre de tipo, el compilador ve realmente su sizeof(my_arr)[0] como sizeof aplicado a una expresión: sizeof (my_arr)[0] , donde (my_arr)[0] es la expresión del argumento. El () rodea el nombre de la matriz es puramente superfluo. Toda la expresión se interpreta como sizeof my_arr[0] . Esto es equivalente a su sizeof(my_arr[0]) anterior de sizeof(my_arr[0]) .

(Esto significa, por cierto, que su sizeof(my_arr[0]) anterior de sizeof(my_arr[0]) también contiene un par de superfluos () .)

Es una idea errónea bastante generalizada que la sintaxis de sizeof alguna manera requiere un par de () alrededor de su argumento. Este concepto erróneo es lo que confunde la intuición de las personas al interpretar expresiones como sizeof(my_arr)[0] .