1

I'm trying to figure out the C memory layout of global variables. Here is the program I used:

#include <stdio.h>
int a = 1;
char *b = "moish";
//char b[6] = {'m','o','i','s','h',0};
int c = 3;
int d = 4;
int e = 5;

int main(int argc, char **argv)
{
    printf("location: %p\n",&a);
    printf("location: %p\n", b);
    printf("location: %p\n",&c);
    printf("location: %p\n",&d);
    printf("location: %p\n",&e);
    return 0;
}

When I compiled and ran it I got what I expected, assuming a reasonable alignment in which variable c is located at 0x56294fab001c instead of 0x56294fab001a etc.

location: 0x56294fab0010
location: 0x56294fab0014
location: 0x56294fab001c
location: 0x56294fab0020
location: 0x56294fab0024

When I use char *b = "moish" I get a totally different address:

location: 0x55c676551010
location: 0x55c676350784
location: 0x55c676551014
location: 0x55c676551018
location: 0x55c67655101c

Why is that? I thought the 2 options are equivalent, no?

OrenIshShalom
  • 5,974
  • 9
  • 37
  • 87

2 Answers2

1

This is an actual array

char b[6] = {'m','o','i','s','h',0}; // size is 6 byte

While this is just a pointer which points to a read only memory location where was "moish" placed since its a constant string.

char *b = "moish"; // size is the char pointer size of the architecture

Actually this would be the real equivalent of char b[6] = {'m','o','i','s','h',0};

char b[] = "moshi"; // or char b[6] = "moshi" , does not matter in this case
Eraklon
  • 4,206
  • 2
  • 13
  • 29
  • `char b[6]` is not on the stack. – kiran Biradar Apr 10 '20 at 09:09
  • @kiranBiradar Whops, Yes, edited it. Thanks. – Eraklon Apr 10 '20 at 09:11
  • @kiranBiradar So where is it? even if there is not concept of stack in the C standard, for sure `b[6]` is placed on the stack on all implementations – David Ranieri Apr 10 '20 at 09:14
  • 1
    In the `.data` segment of the executable if it is initialized. If not initialized then its on the `.bss` segment. Local variables stored onto the stack. – Eraklon Apr 10 '20 at 09:17
  • @Eraklon we are talking about `char b[6] = {'m','o','i','s','h',0};`, it seems an array to me (not a string literal) – David Ranieri Apr 10 '20 at 09:19
  • @DavidRanieri Thats an array yes. But "moish" is string literal, but more importantly `char *b` is a pointer! While `char b[6]` is an array. – Eraklon Apr 10 '20 at 09:21
  • *"size is the pointer size of the architecture"* - Note that the sizes of pointers may be different between the types they point to on some systems. -> https://stackoverflow.com/a/13112571/12139179 – RobertS supports Monica Cellio Apr 10 '20 at 09:24
  • And that's what I say ;) `b[6]` is an array, in this case (at global scope) it will be placed in the .data segment, that's true, I didn't pay attention to that – David Ranieri Apr 10 '20 at 09:25
  • 1
    Although the answer that I previously linked is good, I´d wanted to link to that question but couldn´t found it in the time window to edit my comment: https://stackoverflow.com/questions/916051/are-there-any-platforms-where-pointers-to-different-types-have-different-sizes – RobertS supports Monica Cellio Apr 10 '20 at 09:33
0

When you declare

int a;
char b[6];
int c;

the variable b takes up the space between a and c, which is what you expected. When you declare

int a;
char* b;
int c;

and print the addresses of a, b and c, you will get the consecutive addresses as expected BUT you are printing b: not &b. That prints whatever b is pointing to: not the address of b. It is printing the location of "moish" which may be in a completely different area.

Edit Just think of it as RAM and ROM. Anything that can be changed is RAM and anything that cannot be changed is ROM. If you declare

int a;
const char* b = "moish";
const char c[] = "hsiom";
int d;

a, b and d will be in RAM, c and "moish" will be in ROM. Printing &a, &b, &d will result in RAM addresses. Printing b and c will result in ROM addresses. Since b is a variable, it is possible to

b = c;

but not

c = b;
cup
  • 7,589
  • 4
  • 19
  • 42
  • when I change the `char b[6] = { ... }` to `const char b[6] = { ... }` the memory allocation is the same as `char *b = "moish"` ... so I guess it's just a matter of `const`-ness right? – OrenIshShalom Apr 10 '20 at 09:28