在结构上使用 strncpy

Posted

技术标签:

【中文标题】在结构上使用 strncpy【英文标题】:Using strncpy on struct 【发布时间】: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它永远不是适合这项工作的工具。 【参考方案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的字符串”。

以上是关于在结构上使用 strncpy的主要内容,如果未能解决你的问题,请参考以下文章

在结构数组上使用 c++ std::copy

使用堆上结构的结构初始化语法

通过子类结构在 nHibernate 表上使用 Linq 按类型查询

swift 在结构上使用inout参数

在结构上使用 MemoryLayout 会给出不正确的大小

Hyperledger 结构:无法使用 Raft 订购服务在 raspberry pi 4 上创建通道