'Alignment Rules

I'm having a bit of trouble with a homework problem, and I was wondering if anyone could point me in the right direction.

Suppose we are compiling for a machine with 1-byte characters, 2-byte shorts, 4-byte integers, and 8-byte reals, and with alignment rules that require the address of every primitive data element to be an even multiple of the element’s size. Suppose further that the compiler is not permitted to reorder fields. How much space will be consumed by the following array?

A : array [0..9] of record
    s : short;
    c : char;
    t : short;
    d : char;
    r : real;
    i : integer;
end;

Now I understand the problem, for the most part, but the thing that is really throwing me for a loop is the "alignment rules that require the address of every primitive data element to be an even multiple of the element’s size". My book isn't very description when it comes to alignment rules and to be completely honest, I'm not even positive on what an even multiple is. Any help would be appreciated.

Also, I believe the answer is 240-bytes, I just need some help getting there.



Solution 1:[1]

Let's break that down:

"alignment rules" that "require the address of every primitive data element to be an even multiple of the element’s size". It's not very interesting that we're talking about alignment rules; we knew that already.

"require the address" of "every primitive data element" to be "an even multiple of the element’s size". Now we're getting somewhere. We have a requirement and a scope:

Requirement: The address is an even multiple of the element's size.
Scope: Every primitive data element.

So, every time we position an element, we must impose the requirement.

Let us try to position an element in memory. The first thing we will position is the short labelled s. Since a short takes up 2 bytes of memory, and we must make its address a multiple of that size, the address must be a multiple of 2. Let's call that address N.

So, s takes up the space from N up to N + 2. (NOTE: For all of these ranges, the first endpoint is included, but the last endpoint is not. This is the normal way to describe ranges of integers in computer science; in most cases it is by far the most useful and least error-prone way to do it. Trust me.)

We continue with each other field.

c takes up one byte, from N + 2 to N + 3.

We are at N + 3, but we cannot start t there, because N + 3 is odd (since N is even). So we must skip a byte. Thus t ranges from N + 4 to N + 6.

Continuing with this sort of logic, we end up with d from N + 6 to N + 7; r from N + 8 to N + 16; i from N + 16 to N + 20. (NOTE that this only works if we restrict N to be a multiple of 8, or r will be unaligned. This is ok; when we allocate the memory for the array, we can align the start of it however we want - we just have to be consistent about the sequence of data after that point.)

So we need at least 20 bytes for this structure. (That's one of the advantages of the half-open ranges: the difference between the endpoints equals the size. If we included or excluded both endpoints from the range, we'd have to make a +1 or -1 correction.)

Now let's say we try to lay out the array as ten consecutive chunks of 20 bytes. Will this work? No; say that element 0 is at address 256 (a multiple of 8). Now r in element 1 will be unaligned, because it will start at 256 + 20 + 8, which is not divisible by 8. That's not allowed.

So what do we do now? We can't just insert an extra 4 bytes before r in element 1, because every element of the array must have the same layout (not to mention size). But there is a simple solution: we insert 4 bytes of additional padding at the end of each element. Now, as long as the array starts at some multiple of 8, every element will also start at a multiple of 8 (which, in turn, keeps r aligned), because the size is now a multiple of 8.

We conclude that we need 24 bytes for the structure, and thus 24 * 10 = 240 bytes for the array.

Solution 2:[2]

The phrase "an even multiple of the element’s size" may indicate that a 2-byte short must be aligned on a 4-byte boundary, for example.

That seems a bit wasteful to me but, since it's homework, it's certainly possible.

Using those rules, you would have (for an array of size 2):

Offset  Variable  Size  Range
------  --------  ----  -----
     0     s         2    0-1
     4     c         1    2-2
     8     t         2    4-5
    12     d         1    6-6
    16     r         8  16-23
    24     i         4  24-27
    28     *         4  28-31

    32     s         2  32-33
    34     c         1  34-34
    36     t         2  36-37
    38     d         1  38-38
    48     r         8  48-55
    56     i         4  56-59
    60     *         4  60-63

The reason you have the padding is to bring each array element up to a multiple of 16 so that the r variable in each can be aligned to 16 bytes.

So the ten array elements would take up 320 bytes in that case.


It may also mean "even" as in "integral" rather than "multiple of two" (far more likely since it matches reality).

That would make the array:

Offset  Variable  Size  Range
------  --------  ----  -----
     0     s         2    0-1
     4     c         1    2-2
     8     t         2    4-5
    12     d         1    6-6
    16     r         8   8-15
    24     i         4  16-19
    28     *         4  20-23

    32     s         2  24-25
    34     c         1  26-26
    36     t         2  28-29
    38     d         1  30-30
    48     r         8  32-39
    56     i         4  40-43
    60     *         4  44-47

In that case, you have 24 bytes per element for a total of 240 bytes. Again, you need padding to ensure that r is aligned correctly.

Solution 3:[3]

I disagree - I read "an even multiple of the element’s size" as "2-byte shorts must have even addresses", or "4-byte ints must be 4-byte aligned". So, an int at address 0x101 to 0x103 is a bus error, but 0x100 and 0x104 is correct

Solution 4:[4]

Hopefully this clears things out to an extent:(ans would be 236(232+4) to be exact)

import pprint
l=[2,1,2,1,8,4]
count=0
i=0
d={}
while(count<10):
    for ele in l:
        while True:
            if(i%ele==0):
                d[i]=ele
                i=i+ele
                break
            i=i+1
    count+=1
pprint.pprint(d)  

Output :

{0: 2,
 2: 1,
 4: 2,
 6: 1,
 8: 8,
 16: 4,
 20: 2,
 22: 1,
 24: 2,
 26: 1,
 32: 8,
 40: 4,
 44: 2,
 46: 1,
 48: 2,
 50: 1,
 56: 8,
 64: 4,
 68: 2,
 70: 1,
 72: 2,
 74: 1,
 80: 8,
 88: 4,
 92: 2,
 94: 1,
 96: 2,
 98: 1,
 104: 8,
 112: 4,
 116: 2,
 118: 1,
 120: 2,
 122: 1,
 128: 8,
 136: 4,
 140: 2,
 142: 1,
 144: 2,
 146: 1,
 152: 8,
 160: 4,
 164: 2,
 166: 1,
 168: 2,
 170: 1,
 176: 8,
 184: 4,
 188: 2,
 190: 1,
 192: 2,
 194: 1,
 200: 8,
 208: 4,
 212: 2,
 214: 1,
 216: 2,
 218: 1,
 224: 8,
 232: 4}

Solution 5:[5]

ans should be 240 Size of structure will be the alignment of immediate larger structure https://www.google.com/amp/s/www.geeksforgeeks.org/data-structure-alignment/amp/

-s 2 short size 2 byte

-c 2 char 1 byte + 1 paddling

-t 2

-d 2

-r 8

-i 8 int 4 + 4 paddling

=24

so

24*10=240 Max is 8 byte so it should be divisible by 8 according to alignment rules

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Karl Knechtel
Solution 2
Solution 3 Ana Betts
Solution 4 Sven Eberth
Solution 5