2

After much time spent on the internet to find the answer, I didn't get anything.

My question is this: I have a 64-bit system and when I run this code:

#include<iostream>
using std::cout;
class A
{
    char a ; //1
    char b ; //1
    int c;   //4
    int d;   //4
};

int main()
{
    A a1;
    cout<<sizeof(a1);
    return 0;
}

the output is 12, not 16. Why?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Hamza
  • 42
  • 7
  • Why should it be different? Padding is optional and completely up to the compiler. – vandench Feb 21 '22 at 13:59
  • 2
    why did you expect 16? – 463035818_is_not_an_ai Feb 21 '22 at 14:00
  • it is not depends upon 32 bit or 64 bit architecture ? – Hamza Feb 21 '22 at 14:01
  • 1
    It depends on many things (e.g. operating systems/ABI may have different convention [and often strictly follewed to simplify use of libraries]). But `a` and `b` take one byte each and you can put nearby. Then for `c`, you may have faster code if it is on 4 byte boundary, so you pad 2 bytes. `d` is already at 4 byte boundaries. – Giacomo Catenazzi Feb 21 '22 at 14:04
  • 1
    No, it does not depend upon 32-bit or 64-bit architecture. It depends on the compiler and the *particulars* of the architecture. On some 64-bit architectures, that could result in a size of 32. On others, it could be a size of 10. Compiler will usually pad for best performance, but may be changed to small size footprint without incurring misalignment faults, or even changed to no-padding smallest size footprint that requires more CPU cycles to access the member variables (to accommodate misalignment and avoid faults). – Eljay Feb 21 '22 at 14:06
  • @463035818_is_not_a_number : in 64 bit architecture char a ; //1 char b ; //1 int c; //4 read in 1 cycle 8bytes ! and int d; //4 can read read in 2nd cycle 8bytes and 4 become padding ... – Hamza Feb 21 '22 at 14:16
  • @Hamza -- So are you saying the ones who wrote the compiler are wrong? Maybe your assumptions were incorrect. – PaulMcKenzie Feb 21 '22 at 14:20
  • in both cases (32 or 64) the size of the struct could be `42` in principle. In practice it isnt, and the answers explain why, but details of padding and layout are implementation defined – 463035818_is_not_an_ai Feb 21 '22 at 14:22
  • @463035818_is_not_a_number : but in many documentation there is mention .. processor can access 8 bytes but is this case it look like 32 bit architecture . which can access 4,4,4 bytes , – Hamza Feb 21 '22 at 14:24
  • @GiacomoCatenazzi : but can u tell me if any one have 8bytes system then how can its cpu fetch the 4bytes ? in single cycle – Hamza Feb 21 '22 at 14:26
  • @463035818_is_not_a_number : if any one have 64bit system then how can its cpu fetch the 4bytes ? in single cycle. – Hamza Feb 21 '22 at 14:26
  • 2
    This will depend on the CPU and its requirements. – drescherjm Feb 21 '22 at 14:26
  • 1
    @Hamza It seems to me like this is a CPU architecture question, not a C++ question. Alignment requirements for `int` on your platform appears to be `4`. Your question appears to be why your platform has that requirement. – François Andrieux Feb 21 '22 at 14:28
  • i am just trying to explain that your assumption that it **must** be 16 is wrong. And it is wrong without considering any details of the processor, because the compiler is allowed to add more padding when it feels like. What size we can expect with some confidence, because the compiler will not use more than necessary is different. I suppose thats what you meant, but it is important to understand the difference to "it must be 16" – 463035818_is_not_an_ai Feb 21 '22 at 14:29
  • @463035818_is_not_a_number : don't understand why 12 bytes in 64 bit system . – Hamza Feb 22 '22 at 16:06

2 Answers2

2

In the used system sizeof( int ) is equal to 4. So to align the data member c the compiler pads 2 bytes after the variable b. As a result the size of the structure is 12 bytes.

You could get a more visible result dependent on whether a 32 or 64 bit system is used if you would declare data members c and d having the type long. In most 64-nit systems sizeof( long ) is equal to 8.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
2

Padding bytes are added between data members of a structure or class when they are needed to either fulfil the alignment requirements of any of those data members, or (more generally) to optimize access speed to those members.

Now, although the alignment requirements for types such as int are not specified by the C++ Standard, and can vary (or not vary) between 32-bit and 64-bit builds for the same underlying chip (such as the Intel x86-64 systems), the alignment requirement for the char type (and also signed char and unsigned char) is specified by the Standard! From cppreference:

The weakest alignment (the smallest alignment requirement) is the alignment of char, signed char, and unsigned char, which equals 1; the largest fundamental alignment of any type is implementation-defined and equal to the alignment of std::max_align_t (since C++11).

So, as the alignment requirement for the b member is 1, no padding is required between a and b. In your case, the alignment requirement for int is 4 bytes, so two padding bytes must be added before the c member. Thus, 2 × sizeof(char) (= 2) + 2 padding bytes + 2 × sizeof(int) (=8) gives a total size of 12 bytes.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
  • but in many documentation there is mention .. processor can access 8 bytes but is this case it look like 32 bit architecture . which can access 4,4,4 bytes , – Hamza Feb 21 '22 at 14:21
  • @Hamza In fact, my use of the term, "alignment requirement" is probably a bit inaccurate. For example, on both x86 and x64 systems, the *actual requirement* is only 1 byte, but access is considerably optimized for 4-byte `int` alignment and (e.g.) 8-byte `double` or `int64_t` alignment. – Adrian Mole Feb 21 '22 at 14:27
  • can u tell me if any one have 8bytes system then how can its cpu fetch the 4bytes ? in single cycle – Hamza Feb 22 '22 at 16:08
  • CPUs typically have many different fetch instructions. Some work on 1 byte, some on 2, some on 4 and others on 8 or more byte data objects. – Adrian Mole Feb 22 '22 at 16:13
  • but lot of system like 32bit or 64 there is same answer/output of this program 12bytes – Hamza Feb 22 '22 at 17:55