Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
strncpy只复制字符串的一部分_C_String_Strncpy - Fatal编程技术网

strncpy只复制字符串的一部分

strncpy只复制字符串的一部分,c,string,strncpy,C,String,Strncpy,假设我有这样的结构 typedef struct _student { int studentID; char name[30]; char class[10]; char department[10]; } Student; 下面的函数创建Student类型的新变量: Student *new_student(int id, char *name, char *class, char *dept) { Student *s = (Student *)m

假设我有这样的结构

typedef struct _student {
    int studentID;
    char name[30];
    char class[10];
    char department[10];
} Student;
下面的函数创建Student类型的新变量:

Student *new_student(int id, char *name, char *class, char *dept) {
    Student *s = (Student *)malloc(sizeof(Student *));

    s->studentID = id;
    strncpy(s->name, name, sizeof(s->name) - 1);
    s->name[sizeof(s->name) - 1] = '\0';
    strncpy(s->class, class, sizeof(s->class) - 1);
    s->class[sizeof(s->class) - 1] = '\0';
    strncpy(s->department, dept, sizeof(s->department) - 1);
    s->department[sizeof(s->department) - 1] = '\0';
    return s;
}

void display_student(Student *s) {
    printf("Student: %d | %s | %s | %s\n", s->studentID, s->name, s->class, s->department);
}
为了测试我的代码,我只需在main中编写一些简单的代码

int main() {

    Student *s1 = new_student(20111201, "Lurther King Anders Something", "ICT-56", "SoICT");
    Student *s2 = new_student(20111202, "Harry Potter", "ICT-56", "SoICT");
    Student *s3 = new_student(20111203, "Hermione Granger", "ICT-56", "SoICT");
    Student *s4 = new_student(20111204, "Ron Weasley", "ICT-56", "SoICT");
    display_student(s1);
    display_student(s2);
    display_student(s3);
    display_student(s4);

    return 0;
}
然而,结果对我来说是出乎意料和奇怪的:

有人能给我解释一下为什么会有这样奇怪的结果吗!我认为我做事情的方式是正确的,我已经应用了strncpy的安全使用,但我不理解它的输出。

 ... malloc(sizeof(Student *));
分配

sizeof(Student *)
字节。它通常是4或8,因为Student*是指针类型

你可能想要

     ... malloc(sizeof(Student));
更好的是:

Student * s = malloc(sizeof(*s));
甚至没有无用的括号:

Student * s = malloc(sizeof *s); /* sizeof is an operator, not a function. */
将mallocsizeof*s读取为:分配与s指向的字节数相同的字节数。

 ... malloc(sizeof(Student *));
分配

sizeof(Student *)
字节。它通常是4或8,因为Student*是指针类型

你可能想要

     ... malloc(sizeof(Student));
更好的是:

Student * s = malloc(sizeof(*s));
甚至没有无用的括号:

Student * s = malloc(sizeof *s); /* sizeof is an operator, not a function. */
将mallocsizeof*s读取为:分配s指向的字节数

那条线错了。你为一个学生分配你想要使用的内存,但只为一个学生要求足够的内存*

通过将表达式而不是类型传递给sizeof,可以大大降低发生此类错误的可能性。 还有:

作为一个建议,考虑使用,如果必须自行定义。 当然,除非您依赖于将缓冲区的其余部分归零,例如,因为您直接将它们写入文件。 strncpy几乎总是错误的,尽管除了性能之外,您似乎已经熟练地避免了所有的陷阱

那条线错了。你为一个学生分配你想要使用的内存,但只为一个学生要求足够的内存*

通过将表达式而不是类型传递给sizeof,可以大大降低发生此类错误的可能性。 还有:

作为一个建议,考虑使用,如果必须自行定义。 当然,除非您依赖于将缓冲区的其余部分归零,例如,因为您直接将它们写入文件。 strncpy几乎总是错误的,尽管除了性能之外,您似乎已经熟练地避免了所有的陷阱。

好的,首先: mallocsizeofStudent*指针的大小只有4个字节,所以没有足够的内存用于结构。我想知道它到底是怎么工作的,但不管怎样。因此,要获得结构的大小,请使用以下示例:

学生*s=学生*mallocsizeofStudent

在尝试执行以下操作后,在堆中分配新的数据对:

strncpys->name,name,sizeofs->name-1

在这里,您的s->name在内存中有一些垃圾,因为您没有为此内存分配任何数据,您应该使用函数参数中的数据长度

 Student *new_student(int id, char *name, char *classSt, char *dept) 
{
    Student *s = (Student *)malloc(sizeof(Student));

    s->studentID = id;

    strncpy(s->name, name, strlen(name) + 1);
    strncpy(s->classSt, classSt, strlen(classSt) + 1);
    strncpy(s->department, dept, strlen(dept) + 1);

    return s;
}
好的,首先: mallocsizeofStudent*指针的大小只有4个字节,所以没有足够的内存用于结构。我想知道它到底是怎么工作的,但不管怎样。因此,要获得结构的大小,请使用以下示例:

学生*s=学生*mallocsizeofStudent

在尝试执行以下操作后,在堆中分配新的数据对:

strncpys->name,name,sizeofs->name-1

在这里,您的s->name在内存中有一些垃圾,因为您没有为此内存分配任何数据,您应该使用函数参数中的数据长度

 Student *new_student(int id, char *name, char *classSt, char *dept) 
{
    Student *s = (Student *)malloc(sizeof(Student));

    s->studentID = id;

    strncpy(s->name, name, strlen(name) + 1);
    strncpy(s->classSt, classSt, strlen(classSt) + 1);
    strncpy(s->department, dept, strlen(dept) + 1);

    return s;
}

哦,我明白了。非常感谢你。我没看到那件简单的事。我现在就接受你的回答:哦,我明白了。非常感谢你。我没看到那件简单的事。我现在就接受你的回答:我还没听说过strlcpy,我是从C开始的。谢谢你的建议,我会找到更多关于strlcpy不属于C标准的内容@Duccung它是一些平台上的一个扩展。我没有听说过strlcpy,我从C开始。谢谢你的建议,我会发现更多关于strlcpy不是C标准的一部分的信息@Duccung它是某些平台上的一个扩展。您应该使用数据长度这是非常危险的,因为源可能比目标长,因此strncpy将在目标后面写入。此外,无论s->name是否初始化,根据OP代码,sizeofs->name始终为30-1否,您构建了缓冲区溢出陷阱。您给出的是目标缓冲区的大小,而不是输入的长度。您应该使用数据的长度。这是非常危险的,因为源缓冲区可能比目标缓冲区长,因此strncpy将在目标缓冲区后面写入。此外,无论s->name是否初始化,根据OP代码,sizeofs->name始终为30-1否,您构建了缓冲区溢出陷阱。您给出的是目标缓冲区的大小,而不是输入的长度。