在结构上使用 strncpy
Using strncpy on struct
假设我定义了这个 student struct
:
struct student {
char *name;
};
typedef struct student Student
现在我有以下功能:
void add_student(const char *student_name) {
// create new student
Student *new_s;
new_s = malloc(sizeof(Student));
strncpy(new_s->name, student_name, sizeof(new_s->name) - 1)
}
我想将 student_name 添加到新学生结构的名称中。但是因为 const char
和 char
不同,我必须使用 strncpy
.
我这样试过,但是我得到了一个分段错误,怎么了?
您只为该行中的结构new_s
分配内存
new_s = malloc(sizeof(Student));
这包括变量 char* name
,它是一个 pointer to a char
。虽然,您还需要该指针指向的内存。
因此,您需要为结构内部的字符指针分配内存name
。
// create new student
Student *new_s;
new_s = malloc(sizeof(Student));
new_s->name = malloc(100); //assuming you need to store a string of len 100
Haris给出了很好的解决方案。但正如 Florian Zwoch 在评论中所说,您也可以像这样使用 strdup:
void add_student(const char *student_name)
{
Student *new_s = malloc(sizeof(Student));
new_s->name = strdup(student_name);
}
请记住,您必须 free
new_s->name
而不是 free
new_s
。
您还应该检查 malloc
的 return 值和 strdup
的 NULL
值。因为它 returns NULL
如果可用内存不足。
作为旁注,您可以将 struct
和 typedef
缩短为一个语句,如下所示:
typedef struct student {
char *name;
} Student;
正如 Johan Wentholt 在他的回答中正确概述的那样,您必须为 Student
结构及其成员 name
指向的字符串分配内存,但您必须 return 新的结构,以便调用者可以用它做一些事情:
Student *add_student(const char *student_name) {
Student *new_s = malloc(sizeof(Student));
if (new_s) {
new_s->name = strdup(student_name);
}
return new_s;
}
你的代码调用了未定义的行为,因为你没有为字符串分配内存,更糟糕的是,你让 name
成员未初始化(malloc
没有初始化它的内存 return s).
此外,您不应该使用 strncpy
。它 不是 strcpy
的某个安全版本,它是一个 非常 容易出错的函数,大多数程序员对它的语义知之甚少。 切勿使用此功能。如果您看到它已被使用,那么您可能遇到了错误,或者有更好的方法来替换它。
为了完整起见,您的代码:
strncpy(new_s->name, student_name, sizeof(new_s->name) - 1);
会尝试将最多 sizeof(char*)-1
个字符从 student_name
复制到 new_s->name
指向的数组指针中。
如果student_name
较长,目标不会以null终止,
如果较短,目标将用空字节填充到给定大小。
此处目标指针未初始化,大小信息无论如何都是伪造的:您真的想复制字符串中的所有字符加上空终止符,这正是 strcpy
所做的。但是你需要为此分配足够的内存。您可以使用:
new_s->data = malloc(strlen(student_name) + 1);
strcpy(new_s->data, student_name);
Posix 函数 strdup()
在一次调用中完成两个操作:
new_s->data = strdup(student_name);
假设我定义了这个 student struct
:
struct student {
char *name;
};
typedef struct student Student
现在我有以下功能:
void add_student(const char *student_name) {
// create new student
Student *new_s;
new_s = malloc(sizeof(Student));
strncpy(new_s->name, student_name, sizeof(new_s->name) - 1)
}
我想将 student_name 添加到新学生结构的名称中。但是因为 const char
和 char
不同,我必须使用 strncpy
.
我这样试过,但是我得到了一个分段错误,怎么了?
您只为该行中的结构new_s
分配内存
new_s = malloc(sizeof(Student));
这包括变量 char* name
,它是一个 pointer to a char
。虽然,您还需要该指针指向的内存。
因此,您需要为结构内部的字符指针分配内存name
。
// create new student
Student *new_s;
new_s = malloc(sizeof(Student));
new_s->name = malloc(100); //assuming you need to store a string of len 100
Haris给出了很好的解决方案。但正如 Florian Zwoch 在评论中所说,您也可以像这样使用 strdup:
void add_student(const char *student_name)
{
Student *new_s = malloc(sizeof(Student));
new_s->name = strdup(student_name);
}
请记住,您必须 free
new_s->name
而不是 free
new_s
。
您还应该检查 malloc
的 return 值和 strdup
的 NULL
值。因为它 returns NULL
如果可用内存不足。
作为旁注,您可以将 struct
和 typedef
缩短为一个语句,如下所示:
typedef struct student {
char *name;
} Student;
正如 Johan Wentholt 在他的回答中正确概述的那样,您必须为 Student
结构及其成员 name
指向的字符串分配内存,但您必须 return 新的结构,以便调用者可以用它做一些事情:
Student *add_student(const char *student_name) {
Student *new_s = malloc(sizeof(Student));
if (new_s) {
new_s->name = strdup(student_name);
}
return new_s;
}
你的代码调用了未定义的行为,因为你没有为字符串分配内存,更糟糕的是,你让 name
成员未初始化(malloc
没有初始化它的内存 return s).
此外,您不应该使用 strncpy
。它 不是 strcpy
的某个安全版本,它是一个 非常 容易出错的函数,大多数程序员对它的语义知之甚少。 切勿使用此功能。如果您看到它已被使用,那么您可能遇到了错误,或者有更好的方法来替换它。
为了完整起见,您的代码:
strncpy(new_s->name, student_name, sizeof(new_s->name) - 1);
会尝试将最多
sizeof(char*)-1
个字符从student_name
复制到new_s->name
指向的数组指针中。如果
student_name
较长,目标不会以null终止,如果较短,目标将用空字节填充到给定大小。
此处目标指针未初始化,大小信息无论如何都是伪造的:您真的想复制字符串中的所有字符加上空终止符,这正是
strcpy
所做的。但是你需要为此分配足够的内存。您可以使用:new_s->data = malloc(strlen(student_name) + 1); strcpy(new_s->data, student_name);
Posix 函数 strdup()
在一次调用中完成两个操作:
new_s->data = strdup(student_name);