I am trying to understand the memory allocation in C for struct but I am stuck on it.
struct Person {
char *name;
int age;
int height;
int weight;
};
struct Person *Person_create(char *name, int age, int height, int weight)
{
struct Person *who = malloc(sizeof(struct Person));
assert(who != NULL);
who->age = age;
who->height = height;
who->weight = weight;
who->name = strdup(name);
return who;
}
int main(int argc, char *argv[])
{
struct Person *joe = Person_create("ABC", 10, 170, 60);
printf("Size of joe: %d\n", sizeof(*joe));
printf("1. Address of joe \t= %x\n", joe);
printf("2. Address of Age \t= %x\n", &joe->age);
printf("3. Address of Height \t= %x\n", &joe->height);
printf("4. Address of Weight \t= %x\n", &joe->weight);
printf("5. Address of name \t= %x\n", joe->name);
...
What I don't understand is the memory allocation for this struct. On my printout I see this:
Size of joe: 24
1. Address of joe = 602010
2. Address of Age = 602018
3. Address of Height = 60201c
4. Address of Weight = 602020
5. Address of name = 602030
Questions:
*name
being calculated as the name points only to
first char?There is no gap between the address of the object joe
and the address of data member age
. This extent is occupied by data member name
.
struct Person {
char *name;
int age;
//...
According to the output
1. Address of joe = 602010
2. Address of Age = 602018
it occupies 8 bytes that is sizeof( char * )
in your platform is equal to 8. And its address coincides with the address of the object joe
itself.
In this statement
printf("5. Address of name \t= %x\n", joe->name);
you did not output the address of name
itself. You printed the value stored in this pointer and this value is the address of the first character of a copy of the string literal "ABC"
that was gotten by using strdup
.
So there is a gap between values in the outputs 4 and 5 because they are different extents of memory. Data member weight
belongs to object joe
while the copy of the string literal "ABC"
is stored outside the object. The object just has data member name
that points to the first character of the copy of the literal.
As name
is a pointer then its size is calculated like
sizeof( char * )
or
sizeof( joe->name )
and equal to 8 as I explained in the beginning of the post.
If you want to determine the length of the string literal you should use standard function strlen
declared in header <string.h>
. For example
printf( "%zu\n", strlen( joe->name ) );
Why there is a gap between the 1 and 2?
A struct's start address is always equal to the address of it's first member. From the C standard:
6.7.2.1-13. A pointer to a structure object, suitably converted, points to its initial member
The first member is not age
, but name
. So the following two lines should print the same address:
printf("1. Address of joe \t= %x\n", joe);
printf("1. Address of name-pointer \t= %x\n", &joe->name);
In your code,
printf("5. Address of name \t= %x\n", joe->name);
does not print the address of the pointer, but the address of the data the pointer points to.
How the size of *name is being calculated as the name points only to first char?
name
is a pointer, which occupies 8 bytes of memory regardless of the size of data it points to (that may be a string as in your case, a single char, an int or whatever).
Why there is a gap between the 4 and 5?
The memory for storing the actual name
string is not within the struct - strdup
allocates memory somewhere to duplicate the string into. This happens to be 16 bytes after the last member of your struct. This memory location is then pointed to by your name
pointer.
Note that padding and memory alignment are a factor only for the size of the struct (they do not matter for your explicitly stated questions). Since the struct contains one pointer (8 bytes on your machine) and 3 integers (4 bytes each), one would assume that the total size is 20 bytes. On most platforms, memory is 8 byte aligned - which is why the size of your struct is rounded up to 24 bytes. This way, if you declare an array of Person
s, each array element starts at an address that is 8 byte aligned, i.e., the address value can be divided evenly by 8.
The only things the c standard guarantees is that the address of the first member is the same as the address of the structure, and that the addresses of subsequent members increases with their position in the structure.
Compilers are allowed to insert spaces between members; this is called padding. Regard it as the compiler optimising the structure for a particular platform.
Arrays must always be contiguous in memory though.
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