C 堆对象如何使用堆栈中的数据?
我已经像这样声明了C 堆对象如何使用堆栈中的数据?,c,pointers,C,Pointers,我已经像这样声明了structfoo: struct foo { const char* name_lower; const char* name_caps //.. }; 我在堆上动态创建foo的实例,并希望在name\u lower和name\u caps成员变量中保存一个值。这是通过功能bar void bar(foo* entry, const char* str, int delimiter_pos) { char l[2] = {str[caps
struct
foo:
struct foo {
const char* name_lower;
const char* name_caps
//..
};
我在堆上动态创建foo
的实例,并希望在name\u lower
和name\u caps
成员变量中保存一个值。这是通过功能bar
void bar(foo* entry, const char* str, int delimiter_pos) {
char l[2] = {str[caps_pos-1], '\0'}; // create new string
char c[2] = {str[caps_pos+1], '\0'};
entry->name_lower = &l[0]; // assign these strings the foo instance
entry->name_caps = &c[0];
}
我很担心,因为我不知道这个代码是否会崩溃。临时创建的数组l
和c
将保存在堆栈上。一旦函数终止,堆栈将被清除,c
和l
可能会消失
这是否意味着
foo
实例将丢失其名称,即其引用?如果是这样,我如何解决这个问题呢?您应该使用char*l=(char*)malloc(2*sizeof(char))编码>然后初始化它;类似于char*c
。然后设置entry->name\u lower=l;条目->名称\u caps=c代码>
分配时,确保检查分配是否成功,即malloc
是否返回非空地址
确保在不再需要内存后释放内存:free(entry->name\u lower);免费(输入->姓名/大写)代码>它不会丢失任何东西。struct
中的指针将保留其值,但内容将发生变化,最终您将获得SIGSEGV
要使char*
持久化,还需要在堆上分配它
void条(foo*entry、const char*str、int分隔符\u pos){
char*l=malloc(2);
char*c=malloc(2);
/*检查l和c是否为空*/
l[0]=str[caps_pos-1];
l[1]='\0';
c[0]=str[caps_pos+1];
c[1]='\0';
条目->名称\u下=l;
条目->名称\u caps=c;
}
请记住,当不再需要结构成员时,还应free()
该结构成员。从注释继续,为l
和c
的新内存块分配/复制和分配起始地址的最简单方法是使用strdup
(来自string.h
):
当不再需要时,不要忘记释放分配给entry->name\u lower
和entry->name\u caps
的内存。如果字符串长度有限制,可以使用char
数组而不是指针。在您的示例中,所有字符串的长度均为1。假设字符串不能超过这个长度,可以使用char[2]
而不是char*
:
struct foo {
char name_lower[2];
char name_caps[2];
//..
};
void bar(foo* entry, const char* str, int delimiter_pos) {
entry->name_lower[0] = str[caps_pos-1];
entry->name_lower[1] = '\0';
entry->name_caps[0] = str[caps_pos+1];
entry->name_caps[1] = '\0';
}
历史注释:
因为这很容易使用,人们习惯了这一点,并强制对字符串长度进行人为限制,导致缓冲区溢出。如果您的字符串不受限制,请使用动态分配,而不要使用char
数组。谷歌搜索“动态内存分配”-我知道动态内存分配的原则。这是否意味着我必须通过调用malloc将l和c存储在堆上?是的,没错。否则,它们将指向在流从条返回后将包含未定义值的地址。是的,因为在函数体结束后,指针不应该被取消引用。另一种放置指针的方法是当函数终止时,函数堆栈帧连同函数的所有局部变量一起被销毁。因此,您必须将1
和c
复制到bar
中的新内存块中,并将新块的起始地址分别分配给entry->name\u lower
和entry->name\u caps
。
struct foo {
char name_lower[2];
char name_caps[2];
//..
};
void bar(foo* entry, const char* str, int delimiter_pos) {
entry->name_lower[0] = str[caps_pos-1];
entry->name_lower[1] = '\0';
entry->name_caps[0] = str[caps_pos+1];
entry->name_caps[1] = '\0';
}