Hans Passant essentially covers all the right ideas, but let me explain a bit more:
Say a
and b
are both aligned to 16 bytes. say, they have address 0x100 and 0x200, for the sake of example.
Now, let's see how the code looks like with i=3
(odd) and i=6
(even)...
a[i+1] = b[i] * 3;
will do [0x120] = [0x318] * 3
(i=3, sizeof double is 8)
or
a[i+1] = b[i] * 3;
will do [0x138] = [0x330] * 3
In both cases, either the left hand side or the right hand side is aligned, while the other one is misaligned (aligned accesses would always end in 0 in hex, misaligned something else).
Now... Let's purposefully misalign a
to a 8 modulo 16 address (say to 0x108, to keep our example).
Let's see how the code looks like with i=3
(odd) and i=6
(even)...
a[i+1] = b[i] * 3;
will do [0x128] = [0x318] * 3
(i=3, sizeof double is 8)
or
a[i+1] = b[i] * 3;
will do [0x140] = [0x330] * 3
both keep the actual accesses aligned and misaligned at the same time.