【问题标题】:C dynamically allocate struct typeC动态分配结构类型
【发布时间】:2021-12-03 13:38:07
【问题描述】:

我有一个定义如下的结构

typedef struct{
    int year;
    char* name;
    int id;
}person;

如何动态分配人员对象并将我的数据插入其中? 我的数据如下所示

    int personYear = 20;
    int personId = 12345678;
    char* personName = "firstname lastname";

我知道我可以做声明

person* p = (person*) malloc(sizeof(person));
p->year = personYear;
p->id = personId;

但在那之后,我该如何插入char* person? 我必须重新分配空间来保存内存空间吗?

 // my thought 
  p->name = (char*) malloc (sizeof(char));
  int counter = 0;
  while (*personName != '\0')
  {
      counter++;
      name = (char*) realloc (name, counter+1) // hold 1 more byte 
      *(name+counter) = '\0'; //make sure intialize the value 
      *(name+counter-1) = *personName;
      personName++;
  }
 //what's next?

真正令人困惑的是,由于 struct 在 C 中具有内存对齐,并且在运行时,我们的程序不知道 person->name 将保存多少字节,我们是否需要为 struct 本身重新分配内存空间?正确的做法是什么?

【问题讨论】:

  • 退后一步;深呼吸; 您实际上希望计算机做什么person->name 是一个指针。这意味着它包含(即它指向)其他东西的地址。你希望它指向什么?
  • 无关:你可以用person* p = malloc(sizeof *p); 代替person* p = (person*) malloc(sizeof(person)); - 你不需要强制转换并使用sizeof 取消引用的指针使它更清晰一些(在许多人看来)。
  • 您不需要一次为字符串重新分配一个字符的空间。只需 malloc 字符串的长度加 1:p->name = malloc(strlen(personName) + 1);strcpy(p->name, personName);。 (注1:sizeof(char)定义为1,所以上面的(strlen(personName) + 1)不需要乘以sizeof(char)。注2:不需要将malloc()的返回值类型转换为另一个指针类型。 ) 一些库实现有一个 strdup() 函数(不是 C17 标准的一部分)来完成上述工作:p->name = strdup(personName);
  • 我建议使用strdup()

标签: c struct dynamic-memory-allocation


【解决方案1】:

解决问题的一种方法是使用灵活的结构成员。它通过在结构之后放置一个数组来工作。在这种情况下,它将是一个带有名称字符串的 char 数组。

typedef struct {
    int year;
    int id;
    char name[]; // flexible member
}person;

分配struct person 时,只需添加额外的strlen(name) + 1 字节,然后将name 复制到那里。

person* make_person(int year, int id, char *name) {
  person *p = malloc(sizeof *p + strlen(name) + 1);
  if (!p) return NULL; // out of memory
  p->id = id;
  p->year = year;
  strcpy(p->name, name);
  return p;
}

【讨论】:

  • 这不是一个非常有用的方法,因为如果你想增加字符串的大小,它会变得更加困难,因为如果没有空间来增加它,realloc 可以重新定位内存跨度>
  • 被禁止,并且无法知道编译时成员名称中有多少个字符
  • @randomNameGenerator, <string.h> 被禁止了?!那么这是某种虐待狂的作业吗?
  • @randomNameGenerator,唯一的办法就是自己实现strlen()。问题的循环或多或少已经实现了:int counter = 0; while (*personName != '\0') { counter++; ... ; personName++; }
  • 是的,它是一个只针对指针的编程硬件 LOL,所以基本上我必须使用指针来实现它
猜你喜欢
  • 2010-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-07
  • 1970-01-01
  • 2014-08-22
相关资源
最近更新 更多