Does C correctly handle sizeof(...) and sizeof ... in this case?
In both cases, the last rofl
is the variable name. A variable name is in scope as soon as it appears; and for the remainder of the current scope, that identifier in an ordinary context(*) always means the variable name.
The sizeof
operator does not introduce any special cases for name lookup. In fact, there are no language constructs that will use the hidden meaning of an identifier.
In practice it is a good idea to not use the same identifier for a type and a variable name.
(*) There are three special contexts for identifiers: label names, structure tags, and structure members. But in all other contexts, all identifiers share a common name space: there are no distinct identifier name spaces for type names versus variable names versus function names etc.
Here is a contrived example:
typedef int A; // "A" declared as ordinary identifier, meaning a type namestruct 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}
In this declaration
rofl * rofl = malloc(sizeof(rofl)); // Is the final rofl here the TYPE?
the name of the variable rofl
hides the typedef name rofl
. Thus in the sizeof operator there is used the pointer rofl
that is the expression has the type int *
.
The same is valid for this declaration
rofl * rofl = malloc(sizeof *rofl);
except that there is used an expression with the dereferenced pointer rofl
that has the type of the typedef name rofl
that is the type int
.
It seems that the confusion arises due to this C grammar definition
sizeof unary-expressionsizeof ( type-name )
However unary-expression
can be a primary expression that is an expression enclosed in parentheses.
From the C Standard (6.5.1 Primary expressions)
primary-expression: ( expression ) //...
So for example if x
is a name of a variable then you may write either
sizeof x
or
sizeof( x )
For clarity you could insert blanks between the sizeof operator and the primary expression
sizeof ( x )operator primary expression
For comparison consider another unary operator: the unary plus. You can write for example
+ x
or
+ ( x )
Now just substitute the unary plus for another unary operator sizeof
.
As for hiding names the problem is resolvable for structures, unions and enumerations because their names include keywords for tags.
For example
typedef struct rofl { int x; } rofl;void test(void) { rofl * rofl = malloc(sizeof( struct rofl));}
In this function with the sizeof operator there is used type-name struct rofl
.
While in this function
typedef struct rofl { int x; } rofl;void test(void) { rofl * rofl = malloc(sizeof( rofl));}
with the sizeof operator there is used a primary expression with the variable rofl
, that has the type struct rofl *
.
There is no "picking" or "choosing" involved. In both cases the rofl
referred to in each sizeof
invocation is the variable, not the type, due to scoping rules. The variable is declared at inner scope, and thus overrides the type name. The parenthesization of the argument to the sizeof
operator is irrelevant.
Best of luck.