Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is sizeof class guaranteed to contain size of elements only [duplicate]

Tags:

c++

sizeof

Given example class

class test
{
public:
test();
~test();
void someMethod();
void someOtherMethod();

private:
int var;
};

is sizeof(test) == sizeof(int), or we cannot make such assumption? Is it platform/compiler dependent?

EDIT:

Motivation for that is to read/write class through stream. Class indeed contains a single integer, with some convenience access methods - highest order byte of integer is reserved for flags, 3 lower bytes represent integer 24 bit number. Given this, idea is to write arrays of such class variables, and read them as plain int if needed. The question quoted as having possible answer doesn't address that aspect - is more about padding with multiple elements.

like image 376
Ilya Kobelevskiy Avatar asked Oct 28 '25 01:10

Ilya Kobelevskiy


2 Answers

In general, no you cannot assume that the size of some arbitrary class is simply the aggregation of the size of it's members. In general, nor should you care*. The compiler can and will change the size of your classes so that their size is is a multiple of some specific number of bytes. The reason it does this is to improve performance. What that number of bytes is is different for every platform.

In this specific example, it might in fact be the case that sizeof (test) == sizeof (int), but I doubt this is the real code that prompted this question.

There are ways you can ensure that it does, but they rely on platform-specific functionality.

First, made sure your class is a POD* and all the members are themselves PODs.

Second, set the packing to 1 byte. Under both GCC and MSVC, the instruction to do this is similar to:

#pragma pack (1)

You should turn this packing off when it is not strictly needed, as it could have a negative impact on performance:

#pragma pack (push, 1)

class test
{
public:
  void someMethod();
  void someOtherMethod();

  int var;
};

#pragma pack (pop)

Note that above I removed the private section. You class is not a POD if it has nonstatic private or protected data members. I also removed the default constructor and destructor for the same reason.

Under both MSVC and GCC, sizeof(test) will equal sizeof(int).


POD: Plain Old Datatype. In order for a class (or struct) to be a POD, it must have no user-defined destructor or constructor, copy-assignment operator, and no non-static members of type pointer to member. In addition, it must have no virtuals, no private or protected non-static members and no base classes. Moreover, any nonstatic data members it does have must also be PODs themselves. In other words, just plain old (public) data.


"Nor should you care." In general, the only times you need to make sure the size of some class is exactly the size of the members is at the boundaries of the system. For example, when moving data in to or out of your program via a socket. The compiler pads your classes for a reason. You should not override the compiler in this unless you have a specific, provable cause.

like image 159
John Dibling Avatar answered Oct 30 '25 17:10

John Dibling


You can not make that assumption.

The compiler is allowed to add padding to improve performance. Maybe your target system can only read 64 bit values. Reading smaller values requires reading 64 bits and then masking to 32 bits. On such a system it would be more efficient to just pad the class out to 64 bits.

If you really need a class or struct to be the exact size that you request, almost every compiler has attributes or pragmas to control the padding.

like image 38
Zan Lynx Avatar answered Oct 30 '25 18:10

Zan Lynx