How is a "struct" organized in memory?

Asked

Viewed 637 times

5

How access to struct? Can I put members in the order I want? How does the compiler know which part of the memory to access? What would this look like?

struct {
   char ch1;
   short s;
   char ch2;
   long long ll;
   int i;
};

1 answer

6


A array is a sequence of elements of a certain type, right? The array is a memory position where you have the first element (0), and then there is another equal element, and so on.

If the data type is 1 byte and the array has 10 elements, it will occupy 10 bytes, one after the other, as if it were one thing.

If the type has 4 bytes, the full object will have 40 bytes.

To navigate between elements, when to access var[5], where it stores ints, is actually accessing *(var + 5 * sizeof(int)), then probably (depends on the platform) if var points to 100 memory address (hypothetically), this access will occur at 120 memory position (100 + 5 * 4).

Well, a struct is a sequence of members of various types. These members are arranged one after the other as occurs in the array, but the size of each member will vary according to its type. Then the access of var.ll is accessed by the variable address, plus the size of all previous members. In this question example would be var + sizeof(ch1) + sizeof(s) + sizeof(ch2). Actually you have to consider alignment also. Then the most correct is to use the operator offsetof which gives the correct displacement of each member.

To make it easier, let’s line it up and see how it looks:

#include <stdio.h>
#include <stddef.h>

typedef struct {
    long long ll;
    int i;
    short s;
    char ch1;
    char ch2;
} Tipo; 
    
int main(void) {
    Tipo var = { .ll = 1000000000000, .i = 1000, .s = 10, .ch1 = 'a', .ch2 = 's' };
    printf("%lld\n", var.ll);
    printf("%i\n", var.i);
    printf("%d\n", var.s);
    printf("%c\n", var.ch1);
    printf("%c\n", var.ch2);
    printf("%lld\n", *((long long*)(((char*)&var) + offsetof(Tipo, ll))));
    printf("%i\n", *((int*)(((char*)&var) + offsetof(Tipo, i))));
    printf("%d\n", *((short*)(((char*)&var) + offsetof(Tipo, s))));
    printf("%c\n", *((char*)(((char*)&var) + offsetof(Tipo, ch1))));
    printf("%c\n", *((char*)(((char*)&var) + offsetof(Tipo, ch2))));
}

Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.

The second sequence of prints produces the same result, but doing arithmetic in hand, which is much more complicated. Let’s let the compiler do it for us.

In the hand is doing:

  • handle variable address var
  • makes a cast to transform everything into byte (char *) and be able to handle bytes freely
  • discovers the member’s displacement and sums with the variable’s address
  • makes a cast for the type of member
  • picks up the contents of the found address

The beauty of C is to treat everything in the most concrete and simple way possible. Understanding is more complicated than actual execution. A structure is just a map for memory addresses.

So in this struct of the example the access would be:

typedef struct {
    long long ll; // na posição 0
    int i;       // na posição 8
    short s;     // na posição 12
    char ch1;    // na posição 14
    char ch2;    // na posição 15
} Tipo;

Browser other questions tagged

You are not signed in. Login or sign up in order to post.