15

I got a program in a book

#include <stdio.h>
int main( )
{
    struct data
    {
        int a    __attribute__( ( aligned ( 8 ) ) ) ;
        char ch  __attribute__( ( aligned ( 1 ) ) ) ;
        float s  __attribute__( ( aligned ( 4 ) ) ) ;    
    } ; 
    struct data e ;
    printf ( "\n%u %u %u", &e.a, &e.ch, &e.s ) ;
    printf ( "\n%d", sizeof ( e ) ) ;
    return 0 ;
}

when I run it on cygwin installed on windows 7 machine. I am getting output

2280712 2280716 2280720 16

why this output I am getting? I was expecting the output

2280712 2280720 2280721 13

Naveen
  • 74,600
  • 47
  • 176
  • 233
user555735
  • 151
  • 1
  • 1
  • 3

3 Answers3

20

A sizeof is always a multiple of largest alignment, as it is actually reports 'step' in chars in array of given type which include padding as between members so padding between array elements required to align them.

Memory layout of struct data will look like this:

 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 ... <--offset
|                                               |
|          struct data   (element [0])          |      (element [1])
|                                               |
|     a     |ch|::::::::|     s     |:::::::::::|     a     |ch|::::...
|                                               |
|<----------- sizeof(struct data) ------------->|

|::::| is padding
  • a is at offset 0 which is obviously a multiple of 8;
  • ch is at offset 4 which is (also obviously) a multiple of 1;
  • s is at offset 8 which is multiple of 4;
  • sizeof(struct data) is equal to offset of [1] (16) which required to be multiple of max(8,1,4) = 8
Vovanium
  • 3,798
  • 17
  • 23
14

The aligned(N) attribute aligns the current data item on an address which is a multiple of N, by inserting padding bytes before the data item. You appear to expect that it does something with packing, which is different.

Your structure appears to be laid out as follows:

Address  Member
-------  -------
2280712  a        [address aligned on multiple of 8]
2280713  a
2280714  a
2280715  a
2280716  ch       [address aligned on multiple of 1]
2280717  (unused)
2280718  (unused)
2280719  (unused)
2280720  s        [address aligned on multiple of 4]
2280721  s
2280722  s
2280723  s
Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
1

aligned(8) just means that the address of &e.a will be aligned by 8. And it is (2280712). sizeof(int) is presumably 4, which is why your char ends up at 2280716 (it has an alignment requirement of 1, so there's no reason for it to be pushed to 2280720). Just add sizeof(int) to your debug output to verify it.

You will need to change your build target settings if you want to use 64-bit ints.

Vishnu CS
  • 748
  • 1
  • 10
  • 24
EboMike
  • 76,846
  • 14
  • 164
  • 167