在下面的代码中,是否应该使用malloc()
之类的函数为指针c
分配内存?我担心递增c
可能会导致它指向另一个变量,从而在调用*c = getchar()
时覆盖它。
char *c;
int count = 0;
while( (*c=getchar()) != 'n' ){
c++;
count++;
}
发布的代码有问题:
c
是未初始化的,写入它有直接的未定义行为,指责它只会使情况变得更糟。- 您不测试文件末尾,也不测试任何数组边界,因此即使
c
指向实际数组,静态、自动或从堆中动态分配malloc()
,也必须检查c
是否保持在该数组的边界内。
这是更正后的版本:
#include <stdio.h>
int main() {
char buf[100];
int c, count, limit;
char *p;
p = buf; /* p points to an automatic array, no malloc needed */
count = 0;
limit = sizeof(buf) - 1; /* maximum number of characters to store */
while ((c = getchar()) != EOF && c != 'n') {
if (count < limit)
*p++ = c;
count++;
}
if (count < limit)
*p = ' ';
else
buf[limit] = ' ';
printf("%sn", buf);
return 0;
}
下面是一个具有内存分配的功能:
#include <stdio.h>
#include <stdlib.h>
int main() {
char *buf, *p;
int c, count, limit;
limit = 99;
p = buf = malloc(limit + 1); /* p points to an array allocated from the heap */
count = 0;
if (buf == NULL) {
printf("allocation failuren");
return 1;
}
while ((c = getchar()) != EOF && c != 'n') {
if (count < limit)
*p++ = c;
count++;
}
if (count < limit)
*p = ' ';
else
buf[limit] = ' ';
printf("%sn", buf);
free(buf);
return 0;
}
笔记:
while ((c = getchar()) != EOF && c != 'n')
是一个经典的 C 习惯用法,用于从标准输入中读取一个字节,并将其存储在int
变量c
中,检查 end if 文件并在单个控制表达式中检查行尾。&&
首先计算其左侧,并且仅当无法从左侧的值确定结果(0
或类型为int
的布尔值或1
时,才计算其右侧。这种特性称为快捷求值,也适用于||
和三元运算符?
/:
。c
必须有一个类型,可以容纳由getchar()
重新调整的所有值:类型unsigned char
的所有值和特殊的负值EOF
。char
、signed char
和unsigned char
都不适合这样做,因为c == EOF
要么错误地匹配377
(ISO-8859-1 中的'ÿ'
(对于已签名的char
案例,要么永远不会匹配未签名的char
案例。int
是c
的正确类型。
是的,应该的。
但是你在这里真的不需要指针。getchar()
返回一个int
。
从文档中我们可以看到getchar
的原型如下所示:
int getchar(void)
它不返回指针,所以是的,如果你想以你的方式使用指针,你必须确保它指向某物。实际上,您的代码会发出以下警告:
warning: assignment makes pointer from integer without a cast [-Wint-conversion]
while( (c=getchar()) != 'n' ){
^
您不一定需要使用malloc
本身,但您必须确保c
指向有效的地址。而且,由于您正在递增c
因此您还负责确保这些地址有效。
简短回答:是的,需要分配内存。
这不仅仅是getchar
-任何时候你都有一个像
char *c;
您必须仔细考虑它指向的位置,以及那里是否有任何分配的内存。
事实上,如果你说的只是
char *c;
你不知道指针c
指向哪里,所以你不知道那里是否有任何分配的内存,但如果我们必须猜测,我们不得不说可能没有。
谚语
char *c;
然后问指针c
指向哪里就像说
int i;
然后问什么
printf("%dn", i);
将打印。 由于我们没有将i
设置为任何值,因此我们不知道它将打印什么。
如果你想读取几个字符,并将它们存储在一个数组中,并使用指针来做到这一点,你可以 - 但你需要分配数组,并使指针指向它。 它可能看起来像这样。 顺便说一下,此时我将指针变量的名称更改为p
,这是指针的更常用名称。 (c
听起来像一个字符,而不是指向字符的指针。
char *p;
char arr[10];
int count = 0;
p = &arr[0];
while( (*p=getchar()) != 'n' ){
p++;
count++;
}
现在指针变量p
有指向的位置,因此使用它来存储带有*p=getchar()
字符是有效的。
话虽如此,我们有两个非常大的问题。 一种是数组被声明为足够大以容纳 10 个字符,但填充数组的循环确实会注意检查这一点。 如果有人在按 Enter 或 Return 之前键入 10 个或更多字符,p
将离开为阵列分配的空间的末端,并开始覆盖其他内存,就像您担心的那样。
第二个困难是我们没有检查文件结尾。 此外,我们无法正确检查文件结尾,因为文件结束指示符EOF
不是有效的字符值,因此不适合*p
,它只能保存字符值。