简体   繁体   English

带有malloc的struct的C内存分配

[英]C memory allocation for struct with malloc

I am trying to understand the memory allocation in C for struct but I am stuck on it. 我试图理解C中的结构的内存分配,但我坚持下去。

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: 问题:

  • Why there is a gap between the 1 and 2? 为什么1和2之间存在差距?
  • Why there is a gap between the 4 and 5? 为什么4和5之间存在差距?
  • How is the size of *name being calculated as the name points only to first char? 如何计算*name的大小,因为名称仅指向第一个char?

There is no gap between the address of the object joe and the address of data member age . 对象joe的地址与数据成员age的地址之间没有间隙。 This extent is occupied by data member name . 此范围由数据成员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. 它占用8个字节,即平台中的sizeof( char * )等于8.并且它的地址与对象joe本身的地址一致。

In this statement 在这个声明中

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

you did not output the address of name itself. 你没有输出name本身的地址。 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 . 您打印了存储在此指针中的值,此值是使用strdup的字符串文字"ABC"的副本的第一个字符的地址。

So there is a gap between values in the outputs 4 and 5 because they are different extents of memory. 因此,输出4和5中的值之间存在差距,因为它们是不同的存储器范围。 Data member weight belongs to object joe while the copy of the string literal "ABC" is stored outside the object. 数据成员weight属于对象joe而字符串文字"ABC"的副本存储在对象外部。 The object just has data member name that points to the first character of the copy of the literal. 该对象只有数据成员name ,指向文字副本的第一个字符。

As name is a pointer then its size is calculated like 由于name是指针,因此其大小计算如下

sizeof( char * )

or 要么

sizeof( joe->name )

and equal to 8 as I explained in the beginning of the post. 如我在帖子开头所解释的那样等于8。

If you want to determine the length of the string literal you should use standard function strlen declared in header <string.h> . 如果要确定字符串文字的长度,则应使用在header <string.h>声明的标准函数strlen For example 例如

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

Why there is a gap between the 1 and 2? 为什么1和2之间存在差距?

A struct's start address is always equal to the address of it's first member. struct的起始地址始终等于它的第一个成员的地址。 From the C standard: 从C标准:

6.7.2.1-13. 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 . 第一个成员不是age ,而是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的大小,因为名称仅指向第一个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). name是一个指针,它占用8个字节的内存,无论它指向的数据大小如何(可能是一个字符串,如你的情况,一个char,一个int或其他)。

Why there is a gap between the 4 and 5? 为什么4和5之间存在差距?

The memory for storing the actual name string is not within the struct - strdup allocates memory somewhere to duplicate the string into. 用于存储实际name字符串的内存不在struct- strdup某处分配内存以将字符串复制到其中。 This happens to be 16 bytes after the last member of your struct. 这恰好是结构的最后一个成员之后的16个字节。 This memory location is then pointed to by your name pointer. 然后,您的name指针指向此内存位置。

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. 由于struct包含一个指针(在您的机器上为8个字节)和3个整数(每个4个字节),因此可以假设总大小为20个字节。 On most platforms, memory is 8 byte aligned - which is why the size of your struct is rounded up to 24 bytes. 在大多数平台上,内存是8字节对齐的 - 这就是为什么结构的大小向上舍入到24字节的原因。 This way, if you declare an array of Person s, each array element starts at an address that is 8 byte aligned, ie, the address value can be divided evenly by 8. 这样,如果声明一个Person数组,则每个数组元素从一个8字节对齐的地址开始,即地址值可以均匀地除以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. c标准保证的唯一内容是第一个成员的地址与结构的地址相同,后续成员的地址随着它们在结构中的位置而增加。

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. 但是数组在内存中必须始终是连续的。

It is due to something called Data alignment . 这是由于称为数据对齐的东西。 To quote from this website 引用本网站

Every data type in C/C++ will have alignment requirement (in fact it is mandated by processor architecture, not by language). C / C ++中的每种数据类型都有对齐要求(实际上它是由处理器体系结构强制实现的,而不是语言规定的)。

And then extending this requirement for structures: 然后扩展结构的这个要求:

Because of the alignment requirements of various data types, every member of structure should be naturally aligned. 由于各种数据类型的对齐要求,结构的每个成员都应该自然对齐。

You can go through this article for a detailed read.. 你可以通过这个文章进行了详细读..

The memory layout of the struct is machine dependent, so you should not bother with that unless you are trying to implement a DBMS or a device driver or something like that. 结构的内存布局取决于机器,因此除非您尝试实现DBMS或设备驱动程序或类似的东西,否则不应该为此烦恼。

sizeof(*name) would equal to sizeof(char) , I do not get what confused you here, can you give further explanation? sizeof(*name)等于sizeof(char) ,我不会在这里弄到你的困惑,你能给出进一步的解释吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM