使用malloc和直接初始化堆栈在内存空间方面的区别
我一直在读“艰难地学习C”,我遇到了一个有趣的问题,我希望有人能详细解释。基本练习是使用一个包含示例Person结构的结构。在第一种情况下,我有一个构造函数ish方法(如果有人不介意在侧边解释:D,我不知道教程为什么这样做),以及如下结构:使用malloc和直接初始化堆栈在内存空间方面的区别,c,memory,struct,C,Memory,Struct,我一直在读“艰难地学习C”,我遇到了一个有趣的问题,我希望有人能详细解释。基本练习是使用一个包含示例Person结构的结构。在第一种情况下,我有一个构造函数ish方法(如果有人不介意在侧边解释:D,我不知道教程为什么这样做),以及如下结构: struct Person { char *name; int age; int height; int weight; }; struct Person *Person_create(char *name, int age, int h
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->name = strdup(name);
who->age = age;
who->height = height;
who->weight = weight;
}
与其他代码一样,它运行良好,但当我打印指向这些结构的指针的内存位置时,如下所示:
int main(int argc, char* argv[]) {
struct Person *joe = Person_create("joe alex", 12, 80, 100);
struct Person *joe = Person_create("frank blank", 20, 72, 140);
}
它们的内存值之差总是正好为40。相比之下,结构构造函数的实现类似于:
struct Person{//is the same as above};
struct Person Person_create (char* name, int age, int height, int weight) {
struct Person newPerson;
newPerson.name = name; //and so on
return newPerson
}
当我打印出joe和frank的内存位置时,使用与上面相同的值初始化,使用上面的实现,它们的内存位置的差异似乎总是20
我研究了一点汇编,我知道编译器根据结构的数据类型分配内存块,所以我想。。在这两种实现中,一个字符数组有这么多的字符,所以n个字符*1=字符空间,然后我有3个整数,所以3*4=12;12+9(Joe Alex\0对吗?)=21。。我可能把\0弄错了,所以它等于20左右,但不管我的结构的具体内存大小如何,我更感兴趣的是为什么两个不同的实现会导致内存大小不同(据我所知,内存成本翻倍是一个相当大的量) 在第一种情况下,进行了4次动态分配:两个名称字符串带有
strdup
,两个人结构带有malloc
。结构地址之间的差异告诉您大致分配了多少内存,包括第一个结构和在第二个结构之前[*]
在第二种情况下,不进行动态分配,但我认为您已经在堆栈上创建了两个Person
对象:
struct Person joe = Person_create("joe alex", 12, 80, 100);
struct Person frank = Person_create("frank blank", 20, 72, 140);
它们地址之间的差异大致告诉您第一个地址占用[*]多少内存
由于没有复制字符串,因此需要使用字符串文字作为名称,或者与Person
struct分开管理其内存。字符串数据不是struct Person
的一部分——永远不会是newPerson.name=name
只存储指针,而不是字符串数据
当您开始从文件或终端读取名称时,这就成了一个麻烦:您必须动态地分配它们,这样您就不会节省任何内存,但您必须编写更多的代码。这个练习可能包括一个Person\u Destroy
函数,该函数可以free
s名称,因此struct Person
的用户不必单独担心这个问题
[*]除了实现不需要一个接一个地分配这些东西,所以您的方法通常不起作用。它只是碰巧在这种情况下给出的结果与分配按您的顺序排列的理论一致。这两种方法在使用方式上有很大差异:
定义:
struct Person*Person\u create(字符*姓名、整数年龄、整数身高、整数体重)
用法:
struct Person*p=Person\u create(…)代码>
Person\u create
函数分配结构。此结构的位置取决于函数的实现。调用者只需要定义一个指向该内存的指针,而不是一个完整的person结构
定义:
struct Person\u create(字符*名称、整数年龄、整数身高、整数体重)
用法:
struct Person p=Person_create(…)代码>
在这里,调用方分配了一个完整的person结构,而不仅仅是一个指针。调用函数时,它返回的数据将复制到调用方的person结构中。因此,结构的位置取决于调用方。首先,在第二个示例中,您没有创建字符串的副本……而且,在第二个示例中,您的函数是按值返回的,因此不清楚“内存位置”是什么意思。也许您可以创建一个简短的自包含示例,我们可以编译它来演示这个问题?您的struct
由3个int
s&onechar
pointer~组成,因此大小可能是4+(4*3)字节。您可以通过调用sizeof
来验证这一点~内存位置的差异并不是确定数据大小的可靠方法。非常感谢,我现在感觉好多了。