Structs and padding
A struct bundles several values, of possibly different types, into one new type:
struct Player {
char name[16];
int hp;
int level;
};
struct Player p = {"Ada", 100, 1};
p.hp = p.hp - 30; // dot reaches a field
In memory, a struct is one block with the fields laid out in the order you declared them. There is nothing hidden: no type tag, no methods, just bytes.
Structs are passed by value like everything else, so a function that takes a struct Player gets a full copy. To change the original (or just avoid copying a big struct), pass a pointer. Then you reach fields with the arrow operator:
void heal(struct Player *pl) {
pl->hp = pl->hp + 20; // same as (*pl).hp
}
pl->hp is simply shorthand for (*pl).hp, which nobody enjoys typing.
Now a surprise. What is sizeof this?
struct Mixed { char a; int b; char c; };
You might say 1 + 4 + 1 = 6. On this runner it is 12. Most CPUs prefer (or require) an int to start at an address that is a multiple of 4, its alignment. So the compiler inserts 3 unused padding bytes after a, and 3 more after c so that in an array of these structs, every element's int stays aligned. Padding is implementation-defined, but this layout is very typical.
Reorder the fields as int b; char a; char c; and it drops to 8. Put big fields first and you waste less space.
Try it yourself
Edit it. Break it. Run it again.#include <stdio.h>
struct Player {
char name[16];
int hp;
};
struct Mixed { char a; int b; char c; };
void heal(struct Player *pl, int amount) {
pl->hp = pl->hp + amount;
}
int main(void) {
struct Player p = {"Ada", 70};
heal(&p, 25);
printf("%s has %d hp\n", p.name, p.hp);
printf("sizeof(struct Player) = %zu\n", sizeof(struct Player));
printf("sizeof(struct Mixed) = %zu, not 6\n", sizeof(struct Mixed));
return 0;
}
Your turn
Type it yourself. That is the whole trick.1Move the point
Finish void move(struct Point *pt, int dx, int dy) so it adds dx to the point's x and dy to its y, using ->. Expected output: (5, -1)
#include <stdio.h>
struct Point {
int x;
int y;
};
void move(struct Point *pt, int dx, int dy) {
}
int main(void) {
struct Point p = {2, 3};
move(&p, 3, -4);
printf("(%d, %d)\n", p.x, p.y);
return 0;
}
2Spot the padding
Define two structs with the same three fields in different orders: struct Loose with char a; int b; char c; and struct Tight with int b; char a; char c;. Print their sizes with sizeof:
Loose: 12Tight: 8
#include <stdio.h>
// define struct Loose and struct Tight here
int main(void) {
printf("Loose: %d\n", 0);
printf("Tight: %d\n", 0);
return 0;
}