array - ¿C maneja correctamente sizeof(...) y sizeof... en este caso?
sizeof string (3)
En ambos casos, el último rofl
es el nombre de la variable. Un nombre de variable está en el alcance tan pronto como aparece; y para el resto del alcance actual, ese identificador en un contexto ordinario (*) siempre significa el nombre de la variable.
El operador sizeof
no introduce ningún caso especial para buscar nombres. De hecho, no hay construcciones de lenguaje que usen el significado oculto de un identificador.
En la práctica, es una buena idea no usar el mismo identificador para un tipo y un nombre de variable.
(*) Hay tres contextos especiales para identificadores: nombres de etiquetas, etiquetas de estructura y miembros de estructura. Pero en todos los demás contextos, todos los identificadores comparten un espacio de nombre común: no hay espacios de nombres de identificadores distintos para los nombres de los tipos frente a los nombres de las variables en comparación con los nombres de las funciones, etc.
Aquí hay un ejemplo artificial:
typedef int A; // "A" declared as ordinary identifier, meaning a type name
struct A { A A; }; // "A" declared as struct tag and member name -- OK as these are three different name spaces. Member type is "int"
A main() // int main() - ordinary context
{
struct A A(); // "A" declared as ordinary identifier, meaning a function name; hides line 1''s A
// A C; // Would be error: ordinary A is a function now, not a typedef for int
struct A B; // OK, struct tags have separate name space
A:+A().A; // OK, labels and struct members have separate name space, calls function
goto A; // OK, label name space
}
En el siguiente código, ¿son equivalentes las funciones test
y test2
?
typedef int rofl;
void test(void) {
rofl * rofl = malloc(sizeof(rofl)); // Is the final rofl here the TYPE?
}
void test2(void) {
rofl * rofl = malloc(sizeof *rofl); // Is the final rofl here the VARIABLE?
}
En otras palabras:
- ¿El
rofl
ensizeof(rofl)
elige correctamente el tipo derofl
debido a los paréntesis? - ¿El
rofl
ensizeof *rofl
elige correctamente la variablerofl
debido a la falta de paréntesis?
Nota: Este es un ejemplo tonto, pero en la práctica puede ocurrir que tengas un nombre de tipo que sea igual al nombre de una variable. De ahí la pregunta.
En esta declaración
rofl * rofl = malloc(sizeof(rofl)); // Is the final rofl here the TYPE?
el nombre de la variable rofl
oculta el tipodef nombre rofl
. Por lo tanto, en el operador sizeof se usa el puntero rofl
que es la expresión tiene el tipo int *
.
Lo mismo es válido para esta declaración
rofl * rofl = malloc(sizeof *rofl);
excepto que se usa una expresión con el puntero desreferenciado rofl
que tiene el tipo del tipodef nombre rofl
que es el tipo int
.
Parece que la confusión surge debido a esta definición de gramática C
sizeof unary-expression
sizeof ( type-name )
Sin embargo unary-expression
puede ser una expresión primaria que es una expresión encerrada entre paréntesis.
Del estándar C (6.5.1 expresiones primarias)
primary-expression:
( expression )
//...
Entonces, por ejemplo, si x
es un nombre de una variable, entonces usted puede escribir
sizeof x
o
sizeof( x )
Para mayor claridad, podría insertar espacios en blanco entre el operador sizeof y la expresión primaria
sizeof ( x )
operator primary expression
Para comparar, considere otro operador unario: el más único. Puedes escribir, por ejemplo
+ x
o
+ ( x )
Ahora simplemente sustituya el más único por otro tamaño de operador unario.
En cuanto a ocultar nombres, el problema se puede resolver para estructuras, uniones y enumeraciones porque sus nombres incluyen palabras clave para etiquetas.
Por ejemplo
typedef struct rofl { int x; } rofl;
void test(void) {
rofl * rofl = malloc(sizeof( struct rofl));
}
En esta función con el operador sizeof se usa type-name struct rofl
.
Mientras está en esta función
typedef struct rofl { int x; } rofl;
void test(void) {
rofl * rofl = malloc(sizeof( rofl));
}
con el operador sizeof se usa una expresión primaria con la variable rofl
, que tiene el tipo struct rofl *
.
No hay ninguna "elección" o "elección" involucrada. En ambos casos, el rofl
hace referencia en cada sizeof
invocación es la variable, no el tipo, debido a las reglas de alcance. La variable se declara en el ámbito interno y, por lo tanto, anula el nombre del tipo. La paréntesis del argumento para el operador sizeof
es irrelevante.
La mejor de las suertes.