I am new to C and I am trying to understand how the memory allocation is being done by the compiler. Here is a piece of code that I wrote to understand what is happening:
#include<stdio.h>
int main(void){
int x=10;
char y='A';
printf("x: %p \ny: %p\n", &x, &y);
return 0;
}
Output:
x: 0x7fffcc33e10c
y: 0x7fffcc33e10b
Int occupies 4bytes and Char occupies 1byte. So how is it that the locations where these variables are stored are consecutive? I am not able to understand this.
As @Rup suggested in the comments below, I tried adding more integers to the code:
#include<stdio.h>
int main(void){
int x=10;
int m = 11;
int n = 11;
int o = 11;
char y='A';
printf("x: %p \nm: %p\nn: %p\no: %p\ny: %p\n", &x, &m, &n, &o, &y);
return 0;
}
I got the following output:
x: 0x7fff825c2e68
m: 0x7fff825c2e6c
n: 0x7fff825c2e70
o: 0x7fff825c2e74
y: 0x7fff825c2e67
the space for y is allocated as 1byte and the x,m,n,o integers are allocated 4bytes. Thank you for all your responses.
How memory for variables is allocated is entirely a function of the implementation - the answer will vary from platform to platform. Variables don't have to be laid out in the order they were declared, and depending on alignment requirements, there may be "holes" (unused bytes) between the end of one variable and the beginning of another.
Here's what's likely happening on your system (all byte values in hex format):
+----+
y: | 41 | 0x7fffcc33e10b
+----+
x: | 0a | 0x7fffcc33e10c // assuming little-endian representation
+----+
| 00 | 0x7fffcc33e10d
+----+
| 00 | 0x7fffcc33e10e
+----+
| 00 | 0x7fffcc33e10f
+----+
On x86 and similar platforms, the stack grows "downward" towards decreasing addresses (x86 is also little-endian, so the addressed byte is the least significant byte of a multi-byte object). So x is allocated "first" at address 0x7fffcc33e10c, and then y is allocated at the next available object address. Since y is a char and only a single byte wide, that next available address is 0x7fffcc33e10b. If y were also a 4-byte int, then the next available address would be 0x7fffcc33e108, and the layout would be something like this:
+----+
y: | 41 | 0x7fffcc33e108
+----+
| 00 | 0x7fffcc33e109
+----+
| 00 | 0x7fffcc33e10a
+----+
| 00 | 0x7fffcc33e10b
+----+
x: | 0a | 0x7fffcc33e10c
+----+
| 00 | 0x7fffcc33e10d
+----+
| 00 | 0x7fffcc33e10e
+----+
| 00 | 0x7fffcc33e10f
+----+
EDIT
An interesting exercise would be to declare
int x = 10;
char y = 'A';
int z = 20;
and see how they're laid out. If they were laid out in the order declared, then you will likely see one or more unused bytes between y and z, since most platforms require multi-byte objects to start at an even address. I wouldn't be surprised if a compiler decided to lay them out as x, z, y, since that would minimize any such "holes".
EDIT OF THE EDIT
Tried it myself, got the following result:
Item Address 00 01 02 03
---- ------- -- -- -- --
x 0x7ffee73b8a78 0a 00 00 00 ....
y 0x7ffee73b8a77 41 0a 00 00 A...
z 0x7ffee73b8a70 14 00 00 00 ....
Three unused bytes between y and z, so 4-byte objects clearly must be aligned to addresses that are multiples of 4. Graphically, we have
+----+
z : | 14 | 0x7ffee73b8a70
+----+
| 00 | 0x7ffee73b8a71
+----+
| 00 | 0x7ffee73b8a72
+----+
| 00 | 0x7ffee73b8a73
+----+
| ?? | 0x7ffee73b8a74
+----+
| ?? | 0x7ffee73b8a75
+----+
| ?? | 0x7ffee73b8a76
+----+
y: | 41 | 0x7ffee73b8a77
+----+
x: | 0a | 0x7ffee73b8a78
+----+
| 00 | 0x7ffee73b8a79
+----+
| 00 | 0x7ffee73b8a7a
+----+
| 00 | 0x7ffee73b8a7b
+----+
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With