Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does C correctly handle sizeof(...) and sizeof ... in this case?

In the following code, are the functions test and test2 equivalent?

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? } 

In other words:

  1. Does rofl in sizeof(rofl) correctly pick the rofl type because of the parentheses?
  2. Does rofl in sizeof *rofl correctly pick the rofl variable because of a lack of parentheses?

Note: This is a silly-looking example, but it can actually happen in practice that you have a type name that's the same as a variable name. Hence the question.

like image 886
ccoder987 Avatar asked Nov 15 '17 01:11

ccoder987


People also ask

Does sizeof work on arrays?

The sizeof() operator returns pointer size instead of array size. The 'sizeof' operator returns size of a pointer, not of an array, when the array was passed by value to a function.

How does sizeof operator work in C?

The sizeof operator is the most common operator in C. It is a compile-time unary operator and used to compute the size of its operand. It returns the size of a variable. It can be applied to any data type, float type, pointer type variables.

Does sizeof need parenthesis?

The parenthesis belong to the printf but not to sizeof . When sizeof is applied to a parenthesized type name, I like to think of that as a cast of nothing -- "returning" just the type. @pmg: You can certainly think of it that way, but I find it misleading.


1 Answers

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 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 } 
like image 163
M.M Avatar answered Sep 20 '22 11:09

M.M