Reputation: 2569
I've been reading about data alignment and structure padding.I've started from here and just to express my understanding, I can say an element or a data e
of type T
is naturally aligned if its address a
is a multiple of its data size[sizeof T
],
let's consider
struct test{
short a;
char b;
};
constexpr auto size = sizeof test
is 4 due to struct test
's max alignment(short
)
and then I went here, the very first answer did a good explanation about data alignment, the author used this example
data1: "ab"
data2: "cdef"
|a b c d| |e f 0 0|
Given the memory access granularity is 4 byte, I am going to make an assumption here like data1
is of 2
byte and data2
is of 4 byte
, since the data2
begins at an odd address or its address isn't the multiple of 4 byte
which is considered as a misaligned data, so accessing data2
will have a different effect based on the architecture.
here comes the padding to make data2
to be naturally aligned by adding junkies(or pure 0s), at the end we have
|a b 0 0| |c d e f|
So far fine, now let's wrap the two data' into a struct
struct wrap{
data1: "ab"
data2: "cdef"
};
Now by considering the max alignment, the wrap
size would become 8
with two-byte padding.
here I am, in the case of struct wrap
whether it is with padding or without padding the processor actually needs two cycles(given a WORD size is 4 byte) to fetch the wrap
object right?
so why do we need padding?
without padding:
|a b c d| |e f 0 0|
assume the processor fetched the 8 byte wrap object
, data1
is of two bytes so it can hold "ab" remaining will be truncated (just as how padded bits would be truncated)
and data2
can read consecutive 4 bytes from its address (which reads "cdef") rest were truncated, So why do we need padding here or I just got it wrong?
the second question which more or less similar to above
struct test2{
short a; //2 byte
char _3,_4,_5,_6,_7,_8,_9,_10,_11 ;
};
and the sizeof test2
will give 12, given now the memory access granularity(changing WORD = 8) is 8-byte then the test2
's object gonna occupy two WORD, again with or without padding it is going to occupy two WORD, so two cycles needed regardless of test2
's alignment to fetch its object, if this is the case why does padding matter here? why 12, not 11 though both needs two cycles in an 8-byte boundary?
final question,
struct final{
char a;
int b;
};
let's say the struct final
is packed(no alignment) and the var test::b
going to be placed at the odd address
memory ( just a theoretical representation)
0 1 2 3 4 5 6 7
tets::a:1 test::b:1 test::b:2 test::b:3 test::b:4
test::b:x
am not meaning bit fields here
I've learned that as long I access test::b using object via `. or ->' it will be fine but when I take the address of it
int * p = &(test::b) ; (void)*p;
this statements will either take a performance hit or crash.
Again if the WORD = 8 bytes then the struct final
's object will get into memory in one cycle and let's say the pointer p
holds the address 1
which is odd, but can't just the deference of *p
copy the bits starting from address 1
up to its pointing to element type( 4-byte )into memory? why there is a problem here? what I've been missing to account for?
Upvotes: 0
Views: 330
Reputation:
The problem with data misalignment is not related to load/store of whole structs. It appears with access to individual fields.
When a field is misaligned, it takes two read/writes plus byte rearrangement, instead of one. The padded struct is larger, and we don't mind.
Upvotes: 3