我目前正在开发一个程序,该程序涉及为考试创建模板。在允许用户向考试添加问题的功能中,我需要确保我只使用存储数据所需的内存。在对各种输入函数(getc、scanf等)之间的差异进行了大量研究后,我成功地做到了这一点,我的程序似乎正在运行,但我担心一件事。这是我的函数代码,我在有问题的行上加了一条注释:
int AddQuestion(){
Question* newQ = NULL;
char tempQuestion[500];
char* newQuestion;
if(exam.phead == NULL){
exam.phead = (Question*)malloc(sizeof(Question));
}
else{
newQ = (Question*)malloc(sizeof(Question));
newQ->pNext = exam.phead;
exam.phead = newQ;
}
while(getchar() != 'n');
puts("Add a new question.n"
"Please enter the question text below:");
fgets(tempQuestion, 500, stdin);
newQuestion = (char*)malloc(strlen(tempQuestion) + 1); /*Here is where I get confused*/
strcpy(newQuestion, tempQuestion);
fputs(newQuestion, stdout);
puts("Done!");
return 0;
}
让我困惑的是,我曾尝试运行相同的代码,但进行了一些小的更改,以测试幕后到底发生了什么。我试着从我的malloc
中删除+1,我把它放在那里是因为strlen
只计数到但不包括终止字符,我认为我希望包括终止字符。这仍然顺利进行。所以我试着运行它,但使用-1,因为这样做会删除终止字符(换行符,对吗?)之前的内容。尽管如此,它还是在单独的行中显示了所有内容。所以现在我有点困惑和怀疑我对字符数组如何工作的了解。有人能帮我澄清一下这里发生了什么吗,或者也许能为我提供一个资源,更详细地解释这一切吗?
在C中,字符串通常以null结尾。然而,Strlen
只计算null之前的字符。因此,您总是必须在strlen
的值上加一才能获得足够的空间。或致电strdup
。
一个C字符串包含你能看到的字符"abc"加上一个你看不到的字符,这标志着字符串的结束。您将其表示为"\0"。strlen函数使用"\0"来查找字符串的末尾,但不计算。
所以
myvar = malloc(strlen(str) + 1);
是正确的。然而,你尝试的是:
myvar = malloc(strlen(str));
和
myvar = malloc(strlen(str) - 1);
虽然不正确,但可能在某些时候起作用。这是因为malloc通常以块为单位分配内存(比如说,可能以16字节为单位),而不是您要求的确切大小。因此,有时,你可能会"运气好",最终在块的末尾使用"slop"。
C字符串以空字符' '
结尾。当对字符串调用strlen
时,它只计算字符数,直到到达null终止符为止(它本身不计算null终止符)。
例如,如果你这样做:
const char *example = "Hello!";
char *s = calloc(strlen(example), sizeof(char));
printf("%sn", s);
然后将分配字符串s
(它在内存中看起来像这样):
'H', 'e', 'l', 'l', 'o', '!'
但是C字符串需要以null结尾,所以我们分配了为null结尾符' '
保留的额外字节。