Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Reducing the size of struct by changing struct member declaration order

I am trying to understand the size of a struct based on it’s members as described a brief tutorial on data alignment (see here. The article states that "All data is naturally aligned within the structure. If type is located at address 0 the following double x is located with an offset of 8 at address 8 and so on. As a consequence the size of this structure is 48 even though it contains only 37 bytes of meaningful data. And yes, if float m follows directly after type the offset of m will be four and the size of the structure reduced to 40." The sentence

And yes, if float m follows directly after type the offset of m will be four and the size of the structure reduced to 40.

does not make sense to me. Why would the struct size be reduced to 40 just because the order of the members is changed? Is it because double vy is offset by 40 bytes and then an additional 8 bytes are padded resulting in a struct size of 48? While if float m follows directly after type, the offset of double vy is only 32 bytes, and then an additional 8 bytes are added resulting in a struct size of 40?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

enter image description here

I have written a small C program to double check the alignments of the struct members:

/*Outputs:
particle one alignment:
type 0
x 8
y 16
m 24
vx 32
vy 40
struct size --> 48
particle two alignment:
type 0
m 4
x 8
y 16
vx 24
vy 32
struct size --> 40
*/
#include <stdio.h>                                                                           
#include <stdlib.h>                                                                          
                                                                                             
typedef struct ParticleOne {                                                                 
    char type;                                                                               
    double x,y;                                                                              
    float m;         // after `y` member                                                                        
    double vx, vy;                                                                           
} ParticleOne;                                                                               
                                                                                             
typedef struct ParticleTwo {                                                                 
    char type;                                                                               
    float m;         // after `type` member                                                                        
    double x,y;                                                                              
    double vx, vy;                                                                           
} ParticleTwo;                                                                               
                                                                                             
int main() {                                                                                 
    ParticleOne *particle_one = malloc(sizeof(ParticleOne));                                 
    ParticleTwo *particle_two = malloc(sizeof(ParticleTwo));                                 
                                                                                             
    // Particle one alignment/offset information                                                                          
    void *p1_type = &particle_one->type;                                                     
    void *p1_x = (void*)&particle_one->x - p1_type;                                          
    void *p1_y = (void*)&particle_one->y - p1_type;                                          
    void *p1_m = (void*)&particle_one->m - p1_type;                                          
    void *p1_vx = (void*)&particle_one->vx - p1_type;
    void *p1_vy = (void*)&particle_one->vy - p1_type;

    printf("particle one alignment:\n");
    printf("type %d\n", p1_type - p1_type);
    printf("x %d\n", p1_x);
    printf("y %d\n", p1_y);
    printf("m %d\n", p1_m);
    printf("vx %d\n", p1_vx);
    printf("vy %d\n", p1_vy);
    printf("struct size --> %d\n", sizeof(ParticleOne));    

    // Particle two alignment/offset information
    void *p2_type = &particle_two->type;
    void *p2_x = (void*)&particle_two->x - p2_type;
    void *p2_y = (void*)&particle_two->y - p2_type;
    void *p2_m = (void*)&particle_two->m - p2_type;
    void *p2_vx = (void*)&particle_two->vx - p2_type;
    void *p2_vy = (void*)&particle_two->vy - p2_type;

    printf("particle two alignment:\n");
    printf("type %d\n", p2_type - p2_type);
    printf("m %d\n", p2_m);
    printf("x %d\n", p2_x);
    printf("y %d\n", p2_y);
    printf("vx %d\n", p2_vx);
    printf("vy %d\n", p2_vy);
    printf("struct size --> %d\n", sizeof(ParticleTwo));

    return 0;
}

>Solution :

With the original byte order, we need:

  • One byte for char type.
  • Seven bytes to make the following double aligned to a multiple of eight bytes.
  • 16 bytes, eight for each of x and y in double x,y.
  • Four bytes for float m.
  • Four bytes to make the following float aligned to a multiple of eight bytes.
  • 16 bytes, eight for each of vx and vy in double vx,vy.

That is 1+7+16+4+4+16 = 48 bytes.

With float moved, we need:

  • One byte for char type.
  • Three bytes to make the following float aligned to a multiple of four bytes.
  • Four bytes for float m.
  • 16 bytes, eight for each of x and y in double x,y.
  • 16 bytes, eight for each of vx and vy in double vx,vy.

That is 1 + 3 + 4 + 16 + 16 = 40 bytes.

Observe that no bytes were needed between the float and the double because the float ended at a multiple of eight bytes.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading