C memory allocation for struct with malloc

I am trying to understand the memory allocation in C for a structure, 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 do not understand is the memory allocation for this structure. In my listing, I see the following:

 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:

  • Why is there a gap between 1 and 2?
  • Why is there a gap between 4 and 5?
  • How is the size of *name calculated, since the name only points to the first char?
+6
source share
5 answers

There is no space between the address of the joe object and the address of the age data element. This area is occupied by the name data element.

 struct Person { char *name; int age; //... 

According to the output

 1. Address of joe = 602010 2. Address of Age = 602018 

it takes 8 bytes, and sizeof( char * ) in your platform is 8. And its address matches the address of the joe object itself.

In this statement

 printf("5. Address of name \t= %x\n", joe->name); 

You did not display the address name . You typed the value stored in this pointer, and this value is the address of the first character of the copy of the string literal "ABC" that was obtained using strdup .

Thus, there is a difference between the values ​​in outputs 4 and 5, since they represent different amounts of memory. The weight data element belongs to the joe object, and a copy of the string literal "ABC" is stored outside the object. An object has only a name data element that points to the first character of a copy of a literal.

Since name is a pointer, then its size is calculated as

 sizeof( char * ) 

or

 sizeof( joe->name ) 

and equal to 8, as I explained at the beginning of the post.

If you want to determine the length of a string literal, you must use the standard strlen function declared in the <string.h> header. for instance

 printf( "%zu\n", strlen( joe->name ) ); 
+9
source

Why is there a gap between 1 and 2?

The start address of the structure is always equal to the address of its first member. From standard C:

6.7.2.1-13. A pointer to a structure object, appropriately transformed, points to its initial member

The first member is not age , but name . Thus, 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 pointed to by the pointer.

How is the size * of the name calculated since the name only points to the first char?

name is a pointer that takes up 8 bytes of memory regardless of the size of the data it points to (it could be a string, as in your case, one char, int, or something else).

Why is there a gap between 4 and 5?

The memory for storing the actual name string is not part of the structure - strdup allocates memory somewhere to duplicate the string. This will be 16 bytes after the last member of your structure. This memory location indicates your name pointer.

Note that filling and aligning the memory is a factor only for the size of the structure (they do not matter for your explicitly asked questions). Since the structure contains one pointer (8 bytes on your computer) and 3 integers (4 bytes each), we can assume that the total size is 20 bytes. On most platforms, 8 bytes are aligned β€” so your structure is rounded to 24 bytes. Thus, if you declare an array from Person s, each element of the array begins with an address that is aligned by 8 bytes, i.e. The address value can be evenly divided by 8.

+7
source

The only thing that the standard c guarantees is that the address of the first element matches the address of the structure and that the addresses of subsequent members increase with their position in the structure.

Compilers are allowed to insert spaces between members; this is called a supplement. Think of it as a compiler that optimizes the structure for a particular platform.

Arrays should always be contiguous in memory.

+3
source

This is due to what is called Data Alignment . Quote this site

Each data type in C / C ++ will have an alignment requirement (in fact, it is determined by the processor architecture, not the language).

And then expanding this requirement for structures:

Due to the alignment requirements of various data types, each member of the structure must be naturally aligned.

You can read this article for more details ..

0
source

The layout of the structure memory is machine-dependent, so you should not worry about it unless you are trying to implement a DBMS or device driver or something like that.

sizeof(*name) will be equal to sizeof(char) , I do not understand what bothers you, can you give additional explanations?

-2
source

All Articles