在内存空间方面使用malloc和直接初始化到堆栈之间的区别

时间:2012-05-24 09:11:52

标签: c memory struct

我一直在阅读“以艰难的方式学习C”,我遇到了一个有趣的问题,我希望有人可以详细解释。基本练习是使用涉及示例Person结构的结构。在第一种情况下,我有一个构造函数方法(我不完全明白为什么教程这样做,如果有人不介意在旁边解释:D)以及像这样的结构:

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.

我研究了一些程序集,我知道编译器根据结构的数据类型分配内存块,所以我在想..在任一实现中,char数组都有这么多的字符所以n个字符* 1 = char空间,然后我有3个整数,所以3 * 4 = 12; 12 + 9(Joe Alex \ 0对吗?)= 21 ..我可能得到\ 0错了所以它等于20或者其他东西,但是无论我的结构的具体内存大小如何,我都更感兴趣为什么这两个不同的实现导致内存中的大小不同(据我所知,DOUBLE内存成本相当大)。

2 个答案:

答案 0 :(得分:1)

在第一种情况下,进行了4次动态分配:两个名称字符串strdup和2个人结构malloc。结构地址之间的差异大致告诉您分配了多少内存,包括第一个结构,在第二个结构之前[*]

在第二种情况下,没有进行动态分配,但我想你已经在堆栈上创建了两个Person对象:

struct Person joe = Person_create("joe alex", 12, 80, 100);
struct Person frank = Person_create("frank blank", 20, 72, 140);

它们的地址之间的差异大致告诉你第一个占用多少内存[*]。

由于您尚未复制字符串,因此非常需要使用字符串文字作为名称,或者与Person结构分开管理其内存。字符串数据不是 struct Person的一部分 - 永远不会。 newPerson.name = name只存储指针,而不是字符串数据。

一旦你开始从文件或终端读取名称,这就变得很麻烦:无论如何你必须动态分配它们,所以你不会保存任何内存,但你必须编写更多的代码。该练习可能包含一个Person_Destroy函数free的名称,以便struct Person的用户不必单独担心。

[*]除了不需要实现一个接一个地分配这些东西,所以你的方法一般不起作用。它恰好在这个场合给出了结果,这与分配按照你做出的顺序放置的理论一致。

答案 1 :(得分:0)

这两种方法的使用方式差异很大:

定义:
struct Person *Person_create(char *name, int age, int height, int weight)
用途:
struct Person *p = Person_create(...);
Person_create函数分配结构。此结构的位置取决于函数的实现。调用者只需要定义一个指向这个内存的指针,而不是整个人的结构。

定义:
struct Person Person_create (char* name, int age, int height, int weight)
用途:
struct Person p = Person_create(...);
这里,调用者分配了一个完整的人员结构,而不仅仅是一个指针。调用该函数时,它返回的数据将被复制到调用者的人员结构中。所以结构的位置取决于调用者。