Member Avatar for Rahul47

Hi guys, here is my code for sizeof() problem.

#include<stdio.h>

struct student{
    char name[30];
    int roll_no;
    float marks;
};
int main(){
    struct student s;
    printf("\nSize of Name:       %d Bytes.", sizeof(s.name));
    printf("\nSize of Roll No:    %d Bytes.", sizeof(s.roll_no));
    printf("\nSize of Marks:      %d Bytes.", sizeof(s.marks));
    printf("\nSize of S Total:    %d Bytes.", sizeof(s));
    getch();
    return 0;
}

8025870ce6a64155b9baebc03218232b

I don't understand how is 30 + 4 + 4 = 40 ? Anyone have any idea on this one ?

As a general rule, processors access memory in chunks of a particular size (a "word"). A structure will be "padded" with unused memory so that the variables are aligned with these "words", making reading faster and simpler.

If I had to guess, your structure actually looks like this in memory:

30 bytes for name.
2 bytes unused, empty space.
4 bytes for roll number.
4 bytes for marks.

http://en.wikipedia.org/wiki/Data_structure_alignment#Data_structure_padding

Member Avatar for Rahul47

I tested with and without char name[30], and found that padding is added only when character string is present. Even if there were int and float present there was no padding addded.

Thanx for clarification.

If you added char name[16] no padding would be needed either.

Member Avatar for Rahul47

If you added char name[16] no padding would be needed either.

I observed that if size is integral of 8 then there is no padding done, otherwise there is padding of 2 or 3 Bytes.

It all depends upon the word size of the architecture. A 32-bit system will be 4 byte aligned. 64-bits will be 8 byte aligned. This is a definite case of caveat programmer (programmer beware)! :-) A lot of new developers have been bit by this.

Member Avatar for Rahul47

@rubberman: So what could be possible negative implications ?

Some compilers let you select the padding size, or no padding at all regardless of what the members of the structure consist of. If I'm writing a program to transfer structures to another system then I use no padding. The problem with that is accessing members may be a little slower.

#pragma pack(0) // no padding
struct foo
{
   char name[20];
   int x;
   int y;
}
#pragma pack() // return to default

There are a couple of negative implications.

Firstly if you compile and run a program on 1 machine that writes a structure directly to a file in binary form using something like fwrite and reads it using fread and then you try and compile and run the same programme on a different machine and use the file created on the first machine the second machine may not read it correctly because the different machines may have inserted different padding in different places and may, ultimately have different sizes for the structure.

The second issue is one of memory wastage. Obviously any padding in your structure is not used for anything, it is unused and unusable (unless you are doing something very very suspect with pointers). How you write your structure, the order in which you place the members can effect the amount of padding in the structure, OK only by a few bytes (probably) but if you then have an array of those structures that wastage is multiplied. Now this wastage may be meanless on todays multi-gigabyte memory machines but it can easily be significant on microprocessors with much smaller memory. I have had to deal with this very problem when an array of poorly written structures was using more memory than needed on a platform that was running low on memory. My re-ordering the members of the structure (and replacing a few ints being used as booleans with a bit mapped int) I was able to save 20 bytes per structure and in a 2000 structure array that was about 40kbytes of memory which was significant. That couple with other savings I managed to make resulted in a total saving of around 600kbytes on a platform that only had 16Mbytes to start with around a 3.7% saving, not much but enough to allow the final stage of development take place.

How do you organise a structures members efficiently? Firstly remembering that structure padding can come at the end of the structure as well as between members because the compiler has to be able to correct align the members of the structure in an array of structures too, so for example if you structure had been

struct student{
    int roll_no;
    float marks;
    char name[30];
};

it probably would have had the memory foot print

4 bytes for roll number.
4 bytes for marks.
30 bytes for name.
2 bytes unused, empty space.

and still a size of 40 bytes in order to ensure that in an array of student roll_no was still on the correct byte boundary.

The best way is to order the members of the structure in order of size of the basic type of the member ignoring any array index, i.e. the basic size of the type ignoring array index for name is 1 because it is an array of char. It doesn't matter (too much on all the platforms I've tried) if you order largest to smallest or smallest to largest but you need to choose one of those orders.

// Example assuming 4 byte int, 2 byte short

struct Example {
  char name[29];
  short classnumber;
  char gender;
  short age;
  char coursecode;
  long mark;
  char grade;
};

// Possible memory foot print
// name        29 bytes
// padding     1 byte
// classnumber 2 bytes
// gender      1 byte
// padding     1 byte
// age         2 bytes
// coursecode  1 bytes
// padding     3 bytes
// mark        4 bytes
// grade       1 byte
// padding     3 bytes

// Total size 48 bytes

// Re-order by size of the basic type (largest first)

struct Example {
  long mark;
  short classnumber;
  short age;
  char name[29];
  char gender;
  char coursecode;
  char grade;
};

// Possible memory foot print
// mark        4 bytes
// classnumber 2 bytes
// age         2 bytes
// name        29 bytes
// gender      1 byte
// coursecode  1 bytes
// grade       1 byte

// Total size 40 bytes
commented: Great! +15
commented: good post :) +14

@Banfa: great explanation! We had the same problem once. After an update of our Modula-2 compiler (who did an optimized padding), we could not read the records from a file that was processed with a program compiled with the old compiler! So in a way we had to "recompile" that datafile also. Murphy was never far away, nor was a deadline ...

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.