在struct上使用strncpy

时间:2016-02-14 17:20:03

标签: c struct char const strncpy

我们说我已定义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 charchar不同,我必须使用strncpy

我试过这种方式,但是我遇到了分段错误,错了什么?

3 个答案:

答案 0 :(得分:4)

您只是为此行中的结构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

答案 1 :(得分:2)

正如Johan Wentholt在他的回答中正确概述的那样,你必须为Student结构和它的成员name所指向的字符串分配内存,但是你必须返回新结构,这样调用者才能做到与它有关:

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未初始化它返回的内存)。

此外,您不应使用strncpy。它是 strcpy的某些安全版本,它是一个非常容易出错的函数,大多数程序员都很难理解其语义。 永远不要使用此功能。如果您看到它被使用,您可能会遇到错误,或者有更好的方法来替换它。

为了完整,您的代码:

strncpy(new_s->name, student_name, sizeof(new_s->name) - 1);
  • 尝试将sizeof(char*)-1中的student_name个字符最多复制到new_s->name的数组指针中。

  • 如果student_name更长,目的地将不会以空终止,

  • 如果它更短,目的地将用空字节填充到给定的大小。

  • 这里目标指针未初始化,大小信息仍然是伪造的:你真的想要复制字符串中的所有字符加上空终止符,这正是strcpy所做的。但是你需要为此分配足够的内存。你可以使用:

    new_s->data = malloc(strlen(student_name) + 1);
    strcpy(new_s->data, student_name);
    

Posix函数strdup()在一次调用中执行两个操作:

    new_s->data = strdup(student_name);

答案 2 :(得分:1)

哈里斯给出了一个很好的解决方案。但就像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

您还应该检查mallocstrdup的返回值是否为NULL值。如果内存不足,则返回NULL

在旁注中,您可以将structtypedef缩短为一个语句,如下所示:

typedef struct student {
    char *name;
} Student;