为字符数组分配内存的方法

8
假设你有-
struct Person {
    char *name;
    int age;
    int height;
    int weight; 
 };

如果您执行 -
struct Person *who = malloc(sizeof(struct Person));

C语言如何知道为name变量分配多少内存,因为它可以容纳大量的数据/字符串?我是C语言新手,对内存分配感到困惑。


不要尝试编写多语言源文件。我相信在C++中管理内存的惯用方式是使用RAII(Resource Acquisition Is Initialization)技术。 - pmg
1
不,name只是一个指针,它有一个独特的大小(通常为4或8个字节)。一旦你意识到这一点,你就明白了。 - Christian Rau
10个回答

4
它本身无法分配内存,您需要单独为其分配内存。
struct Person *who = malloc(sizeof(struct Person));

分配足够的内存来存储类型为Person的对象。
Person对象内,成员name只占用与指向char的指针大小相当的空间。
上述malloc仅分配了这么大的空间,要对成员指针进行有意义的操作,您需要单独分配内存。

#define MAX_NAME 124
who->name = malloc(sizeof(char) * MAX_NAME);

现在,成员name指向堆上大小为124字节的动态内存,可以进一步使用。

此外,在使用完成后,您需要记得显式地free它,否则将导致内存泄漏。

free(who->name);
free(who); 

4
我猜测这个问题的标签C++是无效的,因为原帖中提到了“How would C....”和“I am new to C...”。如果这个问题是关于C++的,那么答案与使用std::string类似。 - Alok Save
我标记为C++,因为我认为它们在内存管理方面有相似之处。或者我错了吗?我对C语言是新手,但对编程并不陌生。感谢您的超快速响应。 - Sajal Dutta
2
@ZiG 确实有相似之处(尽管你更愿意使用 new 而非 malloc)。但是在 C++ 中,通常您不必处理任何低级内存管理,例如使用 std::string 来处理字符串,而不是使用普通的字符数组(或指针),或者通过使用 std::vector 来替代手动实现的动态数组。 - Christian Rau
@Zig 别忘了给答案点个赞,如果你觉得它很好并接受它的话。 - Christian Rau
你需要单独为它分配内存。不对,你要为指针所指向的对象分配内存。name 的内存已经足够了。 - Lightness Races in Orbit

4
不要假设存储指向名称的指针的内存与存储名称数据的内存相同。假设字长为4个字节,则有以下内容:
- char *(4个字节) - int(4个字节) - int(4个字节) - int(4个字节) - ================== - 总计:16个字节
C语言知道大小,因为您已经告诉它结构定义中元素的大小。
我想你困惑的是以下内容:
char* 中的内容将是一个内存位置(例如0x00ffbe532),这是实际字符串存储的地方。不要假设结构体的内容是连续的(因为指针)。实际上,你可以相当肯定它们不会是连续的。
因此,为了重申一个例子,如 `struct Person` (这只是一个例子,在实际程序中位置不同):
- 位置:[内容] - 0x0000:[0x00ffbe532] - 0x0004:[10] - 0x0008:[3] - 0x000C:[25] - 0x00ffbe532:[I am a string\0]

1
请不要在您的帖子中签名。 - Lightness Races in Orbit

2

它只为指向 char 的指针分配内存。您需要单独分配内容的内存。

虽然还有其他选项:

如果您可以接受固定大小的最大长度,您可以执行以下操作:

struct Person {
    char name[PERSON_NAME_MAX_LENGTH+1];
    int age;
    int height;
    int weight; 
 };

按照你的示例分配它。

或者你可以声明一个可变大小的结构体,但我不建议这样做,因为它很棘手,并且每个结构体不能有多个可变大小数组:

struct Person {
    int age;
    int height;
    int weight; 
    char name[]; /*this must go at the end*/
 };

然后像这样分配它:

struct Person *who = malloc(sizeof(struct Person) + sizeof(char)*(name_length+1));

2
name成员只是一个指针。指针的大小因底层架构而异,但现在通常为4或8个字节。 name可以指向的数据(如果稍后被分配)应该布置在完全不与struct重合的区域中。
在语言层面上,structname成员指向的内存一无所知;您必须手动管理它。

1

对于指针,结构体只分配了足够指针的内存。您需要为char*创建内存并将值分配给结构体。假设您在某个地方有char* name

struct Person *who = malloc(sizeof(struct Person));
who->name = malloc((strlen(name)+1) * sizeof(char));
strcpy(who->name, name)

可以使用 stdup 来创建 who->name - Ed Heal
我猜你的意思是strdup?如果可以使用,但它不是ANSI C标准的一部分。此代码示例应为有效的ANSI C。 - Matt Esch
问题中从未提到需要有效的 ANSI C。许多实现包括可能被优化的此例程。 - Ed Heal
C的版本没有明确说明,因此我选择了一个适当的标准。 - Matt Esch

1

它将为name指针分配4个字节的空间,但不会为“真实”的字符串分配空间。如果您尝试在那里写入,您将会出现段错误;您需要单独使用malloc(和free)进行内存分配。

在C++中使用string可以减少一些麻烦。


我猜在64位机器上它会分配8B :) - Vyktor

0

不行,你也得这么做。

struct Person *who = malloc(sizeof(struct Person));
who->name = malloc(sizeof(char) * 16); /* for a 15+1 character array */

0

你的结构体中有一个指向名称字符数组的指针,也就是说它将占用足够表示内存地址所需的字节数。

如果你想要实际使用这个字段,你必须为它分配额外的内存。


0

在我的经验中,指针成员占据一个字(实际数据所在的地址),因此大小可能为16个字节(假设一个字是4个字节)。

正如上面所说,您需要单独分配*name的内存,这将释放其他地方所需的大小的内存。


-2

我认为你还需要为名称属性分配内存


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接