Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Objects of size 0

Tags:

c++

I understand that empty classes in C++ have a size of 1 byte. However, I noticed that sizeof() returns 0 for objects of this class(in g++):

    class Boom{
        int n[0];
    }

I can print a valid memory location for a Boom object:

    Boom b;
    cout<<&b;

Is this particular memory location occupied? If I allocate memory later in the program, is there a chance that this location will be used?

like image 849
PrithviJC Avatar asked Feb 19 '14 11:02

PrithviJC


People also ask

Can you make an array of size 0?

Although the size of a zero-length array is zero, an array member of this kind may increase the size of the enclosing type as a result of tail padding. The offset of a zero-length array member from the beginning of the enclosing structure is the same as the offset of an array with one or more elements of the same type.

Why is size of empty class is not zero?

Actually, the standard does not permit objects (or classes) of size 0, this is because that would make it possible for two distinct objects to have the same memory location. This is the reason behind the concept that even an empty class must have a size at least 1. It is known that size of an empty class is not zero.

What is the size of empty object?

The size of an empty class is not zero. It is 1 byte generally. It is nonzero to ensure that the two different objects will have different addresses.

Can we create object of empty class?

C++ allows creating an Empty class, yes! We can declare an empty class and its object. The declaration of Empty class and its object are same as normal class and object declaration.


4 Answers

Arrays cannot have zero size. If your compiler allows you to declare one, then the language doesn't specify how it behaves.

In this case, with this compiler, it does indeed appear that this allows two objects to occupy the same location:

Boom b[2];
std::cout << &b[0] << ' ' << &b[1] << std::endl;

// Output: 0x7fffffb23fdc 0x7fffffb23fdc

But other compilers may behave differently, or simply reject the invalid declaration (as GCC does if you specify -pedantic -Werror).

like image 185
Mike Seymour Avatar answered Sep 28 '22 02:09

Mike Seymour


Code not valid.

A size of 0 is invalid, both for classes and arrays. The C++ standard says:

Sizeof [expr.sizeof]

[...] The size of a most derived class shall be greater than zero [...]

and

Arrays [dcl.array]

In a declaration T D where D has the form

    D1 [ constant-expressionopt] attribute-specifier-seqopt

[...] If the constant-expression (5.19) is present, it shall be an integral constant expression and its value shall be greater than zero [...]


Why compiles? Compiler extension!

If you turn on -pedantic with g++, you will receive the following warning (or error with pedantic-errors):

ISO C++ forbids zero-size array ‘n’

so your program is basically not valid, but can be compiled by means of a compiler extension to the C++ standard (unless you turn this extension off).

Note: Even though your compiler can report 0 for the class, it won't do so for any instance (a.k.a. object) of that class:

#include <iostream>
class Boom {
    int n[0];
};
int main() {
    std::cout << sizeof(Boom) << '\n';   // prints 0
    std::cout << sizeof(Boom()) << '\n'; // prints 1
}

Having objects of size-0 would go simply too far off the standard.

Citation by Stroustroup:

Why is the size of an empty class not zero?

To ensure that the addresses of two different objects will be different. For the same reason, "new" always returns pointers to distinct objects. Consider:

class Empty { };

  void f()
  {
      Empty a, b;
      if (&a == &b) cout << "impossible: report error to compiler supplier";
      Empty* p1 = new Empty;
      Empty* p2 = new Empty;
      if (p1 == p2) cout << "impossible: report error to compiler supplier";
  } 

There is an interesting rule that says that an empty base class need not be represented by a separate byte:

   struct X : Empty {
        int a;
        // ...
   };

   void f(X* p)
   {
       void* p1 = p;
       void* p2 = &p->a;
       if (p1 == p2) cout << "nice: good optimizer";
   }

This optimization is safe and can be most useful. It allows a programmer to use empty classes to represent very simple concepts without overhead. Some current compilers provide this "empty base class optimization".

like image 45
Sebastian Mach Avatar answered Sep 28 '22 04:09

Sebastian Mach


This is a g++ extension; the C++ standard doesn't allow arrays of 0 elements. I think that this extension was originally designed to do what using an incomplete array type as the final element does in C99, but in C99, it's only legal if the struct contains more than one member. As for what happens if you declare an array of Boom, you'll have to ask g++. (C99 avoids this issue by requiring at least one other member.)

The only real use for this feature is for variable length dynmamically allocated objects, e.g.:

struct Array
{
    size_t size;
    int data[];
};

//  ...
Array* p = (Array*)malloc(sizeof(Array) + n * sizeof(int));
p->size = n;

(This uses the C standard syntax.)

In C++, we'd normally just use std::vector and be done with it.

like image 43
James Kanze Avatar answered Sep 28 '22 02:09

James Kanze


In this definition

class Boom{
    int n[0];
}

there are two errors.:) 1. You forgot to place a semicolon after the closing brace. 2. The size of an array may not be set to zero.

And even empty classes have sizes that are not equal to zero. For example

struct A {};

std::cout << sizeof( A ) << std::endl;

will return a value that greater than 0.

like image 31
Vlad from Moscow Avatar answered Sep 28 '22 03:09

Vlad from Moscow