2

Can someone help me to understand behavior of sizeof() operator?

 #include <iostream>

using namespace std;

class A{
    int first;
    double last;
    public:
    A(int a)
    {
        cout << a << endl;
    }
};
int main()
{
    A a(3);
    cout << sizeof(a) << endl;
    return 0;
}

This code prints me size of a as 16 bytes. Size of class is calculated based on its members. So I have 4 bytes (int) + 8 bytes (double) = 12.

So why did I get 16 bytes?

When I comment out int and double members I get 1 byte.

Cornstalks
  • 37,137
  • 18
  • 79
  • 144
  • If you use Visual C++, see https://msdn.microsoft.com/en-us/library/xh3e3fd0.aspx and try the `/Zp1` option to make the output 12. – Christian Hackl May 15 '16 at 19:48
  • No, I use ordinary g++ compiler – Paweł Jarecki May 15 '16 at 19:56
  • GCC is as "ordinary" as Visual C++ :) In any case, every C++ compiler offers similar options. This stuff is inherently implementation-specific. – Christian Hackl May 15 '16 at 19:57
  • Packing and byte alignment and padding can cause what you are seeing. You should also know it is possible to build your struct or class with precise control over size and with no padding. But that is a different question. – 2785528 May 16 '16 at 03:19

3 Answers3

1

The compiler lays out the class interior for speed and other factors, not necessarily for space saving, so it might leave an empty 4-byte block behind a size-4 element before fitting the next element. That makes accessing the next element faster on modern architecture (which is 64-bit based = 8 byte).

Also, be aware that the sizeof of a class object might contain other data that you are not aware of, like pointers to virtual function tables, etc. it is the compiler's job and right to put in there whatever makes the final code run correctly and fast.

Aganju
  • 6,295
  • 1
  • 12
  • 23
  • This is mostly right, except that the way the compiler lays out the class is not necessarily optimised for speed. Other factors are also taken in consideration. In particular, if a platform has a suboptimal ABI that's used by other compilers, then new compilers may end up using that ABI for compatibility, even if they could come up with a faster ABI by dropping the compatibility. –  May 15 '16 at 19:38
  • I think that virtual function tables are saved as a property of the entire class, rather than with each instance of the class. – John D May 15 '16 at 19:50
1

The layout of the fields in the class is implementation-defined, as long as POD classes are compatible with C structs. However, even in C structs implementations add padding for various reasons, like performance. Thus, your compiler is likely adding four bytes of padding after the int field in order to make the double field start at an 8-byte aligned address.

If you specifically need this to not happen, there are ways to control the alignment and padding of classes/structs, which vary among compilers. For example, GCC has syntax similar to __attribute__((packed)) that will remove that padding. This is rarely necessary - mostly when the struct will need to map to a device register - and will usually hurt performance, so avoid it if possible.

Javier Martín
  • 2,537
  • 10
  • 15
0

The default way the compiler packs members into a class is to try and align with word boundaries i.e. multiples of the size of a word (8 bytes on 64-bit machine). To stop packing use #pragma pack(1) or compiler option /Zp. This forces compiler to squash members right up against each other.

A class is not allowed to have a zero size because that might mean that the pointers to two different objects were the same, so it has a minimum size of 1 byte.

John D
  • 1,627
  • 1
  • 11
  • 10