我只是想知道为什么
students[x].firstName=(char*)malloc(sizeof(char*));
这个不需要字符串的长度。
完整代码(来自互联网上的某个地方):
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
typedef struct
{
char* firstName;
char* lastName;
int rollNumber;
} STUDENT;
int numStudents=2;
int x;
STUDENT* students = (STUDENT *)malloc(numStudents * sizeof *students);
for (x = 0; x < numStudents; x++)
{
students[x].firstName=(char*)malloc(sizeof(char*));
printf("Enter first name :");
scanf("%s",students[x].firstName);
students[x].lastName=(char*)malloc(sizeof(char*));
printf("Enter last name :");
scanf("%s",students[x].lastName);
printf("Enter roll number :");
scanf("%d",&students[x].rollNumber);
}
for (x = 0; x < numStudents; x++)
printf("First Name: %s, Last Name: %s, Roll number: %d\n", students[x].firstName, students[x].lastName, students[x].rollNumber);
return (0);
}
解释:
students[x].firstName=(char*)malloc(sizeof(char*));
2条答案
按热度按时间polhcujo1#
根据您使用的平台,线路
很可能相当于
或
因为这是大多数平台上
char *
(指向char
的指针)的大小。这意味着如果用户输入多于3或7个字符(包括终止空字符在内的4或8个字符),则行
将导致buffer overflow,这将调用undefined behavior。这意味着您的程序可能会崩溃或以其他方式行为不当。
因此,你的担心是有道理的。那条线
应该指定足以存储用户输入的最大可能长度的大小,而不是仅指定指针的大小(4或8字节)。
但是,即使指定一个更大的值,如
那么你的程序仍然是不安全的,因为用户仍然可以通过输入一个长度至少为200个字符的单词来引起缓冲区溢出。因此,更安全的做法是写
而不是:
这将把
scanf
写入内存缓冲区的字符数限制为200(199个匹配字符加上终止空字符)。然而,即使这个解决方案更好,它仍然不是理想的,因为如果输入太长,
scanf
将默默地截断输入,并将剩下的行留在输入流上。这意味着下次在输入流上调用scanf
时,这个剩余的输入可能会引起麻烦,因为这是首先读取的内容。由于这个原因,最好总是读取整行输入,如果它太长而不能存储在内存缓冲区中,则用错误消息拒绝输入并提示用户输入新的内容。
下面的代码中有一个使用
fgets
而不是scanf
的例子,因为fgets
更适合阅读整行输入。然而,由于使用fgets
也不是那么容易,所以我在自己创建的两个辅助函数中使用了fgets
。我将这些函数称为get_line_from_user
和get_int_from_user
。这是我从main
调用的两个函数。我不直接从main
调用fgets
。此程序具有以下行为:
请注意,通常建议始终检查
malloc
的返回值,因为否则,如果malloc
由于某种原因失败,则程序将行为不端。我没有将这些检查添加到代码中,因为我不想分散对其他更改的注意力。rsaldnfx2#
@Andreas Wenzel很好地回答了OP代码的错误。
最好避免使用
"%s"
,因为它不能处理名字或姓氏中的空格。考虑放弃所有
scanf()
的使用,转而使用fgets()
。建议使用辅助函数读取名称的替代代码。helper函数中有一些弱点,但根据编码目标,可以很容易地进行改进。还建议一个同样的助手函数来读取学生人数。