All object sizes in C and C++ are defined in terms of bytes, not bits. A byte is the smallest addressable unit of memory on the computer. A bit is a single binary digit, a 0
or a 1
.
On most computers, a byte is 8 bits (so a byte can store values from 0 to 256), although computers exist with other byte sizes.
A memory address identifies a byte, even on 32-bit machines. Addresses N and N+1 point to two subsequent bytes.
An int
, which is typically 32 bits covers 4 bytes, meaning that 4 different memory addresses exist that each point to part of the int
.
In a 32-bit machine, all the 32 actually means is that the CPU is designed to work efficiently with 32-bit values, and that an address is 32 bits long. It doesn't mean that memory can only be addressed in blocks of 32 bits.
The CPU can still address individual bytes, which is useful when dealing with char
s, for example.
As for your example:
struct st
{
int a;
char c;
};
sizeof(st)
returns 8 not because all structs have a size divisible by 4, but because of alignment. For the CPU to efficiently read an integer, its must be located on an address that is divisible by the size of the integer (4 bytes). So an int
can be placed on address 8, 12 or 16, but not on address 11.
A char
only requires its address to be divisible by the size of a char
(1), so it can be placed on any address.
So in theory, the compiler could have given your struct a size of 5 bytes... Except that this wouldn't work if you created an array of st
objects.
In an array, each object is placed immediately after the previous one, with no padding. So if the first object in the array is placed at an address divisible by 4, then the next object would be placed at a 5 bytes higher address, which would not be divisible by 4, and so the second struct in the array would not be properly aligned.
To solve this, the compiler inserts padding inside the struct, so its size becomes a multiple of its alignment requirement.
Not because it is impossible to create objects that don't have a size that is a multiple of 4, but because one of the members of your st
struct requires 4-byte alignment, and so every time the compiler places an int
in memory, it has to make sure it is placed at an address that is divisible by 4.
If you create a struct of two char
s, it won't get a size of 4. It will usually get a size of 2, because when it contains only char
s, the object can be placed at any address, and so alignment is not an issue.