【问题标题】:Using strncpy on struct在结构上使用 strncpy
【发布时间】:2016-05-25 11:56:48
【问题描述】:

假设我定义了这个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

我尝试过这种方式,但是出现分段错误,怎么了?

【问题讨论】:

  • 你可能想看看strdup,而不是strncpy。这听起来与您尝试在此处存档的内容非常接近。
  • 永远不要使用strncpy它永远不是适合这项工作的工具。

标签: c struct char constants strncpy


【解决方案1】:

正如 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较长,则目的地不会以null结尾,

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

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

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

Posix 函数 strdup() 在一次调用中完成这两项操作:

    new_s->data = strdup(student_name);

【讨论】:

  • 这是真的,但我使用的是 baketurtle 提供的示例。
【解决方案2】:

Haris 给出了一个很好的解决方案。但就像 Florian Zwoch 在 cmets 中所说,您也可以像这样使用 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;

【讨论】:

    【解决方案3】:

    你只是在这一行中为结构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
    

    【讨论】:

    • 所以在分配 new_s->name 之后,我可以这样使用 strncpy 吗? strncpy(new_group->name, group_name, )
    • @bakedturtle,唯一的问题是您没有分配内存。否则,添加该行后,您的代码应该可以工作。你为什么不跑过去检查一下。
    • 嗯 - 对我来说看起来像 1 倍。 "...100); --> //假设你需要存储一个长度为 100 的字符串"。字符串长度一般不包含空字符,建议“存储长度不超过99的字符串”。
    猜你喜欢
    • 1970-01-01
    • 2018-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-08
    • 2021-12-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多