Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does sizeof operator prefer object over type?

Tags:

c++

sizeof

#include <iostream> 

int C; 

class C { 
  private: 
    int i[2]; 
  public: 
    static int f() { 
        return sizeof(C); 
    } 
}; 

int f() 
{ 
    return sizeof(C); // why the C can't be the class type C.
} 

int main() 
{ 
   std::cout << "C::f() = " <<C::f() << "," 
             << " ::f() = " <<::f() << std::endl; 
} 

The above code returns: C::f() = 8, ::f() = 4

My question is why the identifier C inside the global function f resolves to the object of type int that has name C, instead of the class type C? Does sizeof have a specific name lookup rule?

Conclusion : From what I read in this https://stackoverflow.com/a/612476/1021388, hiding class names by function/object/enumerator names is for compatibility concerns with C. And to avoid this inadvertent hiding, one should typedef the class to force compiler errors.

like image 275
Rich Avatar asked Oct 26 '15 15:10

Rich


People also ask

What does the sizeof operator do?

The sizeof operator applied to a type name yields the amount of memory that can be used by an object of that type, including any internal or trailing padding. The result is the total number of bytes in the array. For example, in an array with 10 elements, the size is equal to 10 times the size of a single element.

What is the datatype of sizeof?

sizeof can be applied to any data-type, including primitive types such as integer and floating-point types, pointer types, or compound datatypes such as Structure, union etc. sizeof() operator is used in different way according to the operand type.

Why is sizeof () an operator and not a function?

In C language, sizeof( ) is an operator. Though it looks like a function, it is an unary operator. For example in the following program, when we pass a++ to sizeof, the expression “a++” is not evaluated. However in case of functions, parameters are first evaluated, then passed to function.

What does sizeof tell you about a variable struct or datatype?

It returns the size of a variable. It can be applied to any data type, float type, pointer type variables. When sizeof() is used with the data types, it simply returns the amount of memory allocated to that data type.


2 Answers

sizeof isn't the key to this question. It simply happens to be something that can be used both on type name or a variable name. These rules apply to other uses of identifiers as well.

§9.1 [class.name] (c++ standard draft n3797):

  1. ...snip... If a class name is declared in a scope where a variable, function, or enumerator of the same name is also declared, then when both declarations are in scope, the class can be referred to only using an elaborated-type-specifier.

There is a class by the name of C and a variable by the same name in the global scope. Therefore, the class can be referred to only using an elaborated type specifier (class C).

Inside the definition of C, however, the first part of that paragraph is relevant:

§9.1 [class.name]:

  1. A class declaration introduces the class name into the scope where it is declared and hides any class, variable, function, or other declaration of that name in an enclosing scope ...snip...

§9 [class]:

  1. ...snip... The class-name is also inserted into the scope of the class itself; this is known as the injected-class-name ...snip...

So, inside the scope of class C, the injected class name hides the int C declaration from the outer scope. Therefore you can refer to C without elaborated type specifier. To refer to the global int C, you could use ::C

like image 80
eerorika Avatar answered Sep 28 '22 09:09

eerorika


Regarding your question, sizeof does not have any special parsing or evaluation rules.

Consider the following:

#include <iostream>
#include <typeinfo>

int C; 

class C { 
public:
    int i[2]; 
}; 

int main() 
{ 
   // compiles fine:
   int x = C;

   // prints 0:
   std::cout << C << "\n";

   // prints something that corresponds to "int"
   // (or even "int" itself):
   std::cout << typeid(C).name() << "\n";
}

In all three cases, C is taken as the int variable and not as the type name.

If you need a clear distinction, you can always use class C:

#include <iostream>
#include <typeinfo>

int C; 

class C { 
public:
    int i[2]; 
}; 

int main() 
{ 
   // prints something that corresponds to "class C"
   // (or even "class C" itself):
   std::cout << typeid(class C).name() << "\n";

   // prints sizeof(int):
   std::cout << sizeof(C) << "\n";

   // prints sizeof(int) * 2:
   std::cout << sizeof(class C) << "\n";
} 
like image 23
Christian Hackl Avatar answered Sep 28 '22 09:09

Christian Hackl