2
4

5 回答 5

7

我知道我可以使用gets(),除非它显然很糟糕,我不应该使用它。

确切地说,确切地说,它很容易出现缓冲区溢出错误。并且scanf()同样邪恶(部分原因是相同的 - 指定缓冲区长度并非易事,而且无论如何,它比必要的复杂得多,很难做到正确,而且对于简单的原始 I/O 来说过于昂贵),不要也不要使用它。用于fgets()获取用户输入,它通过让您将要写入的缓冲区的长度传递给它,从而避免您被击中脚:

char buf[0x40];
fgets(buf, sizeof(buf), stdin);

既然您知道“如何”,我将向您解释“为什么”。

数组,当传递给函数时,据说会衰减为指针。如果将 a 传递char []给函数,它会将 a 视为char *指向数组的第一个元素。这就是为什么您不必&为 (char) 数组(在概念上是 C 中的字符串)显式使用“addressof”()运算符。

如果你使用它,你得到的不是指向数组第一个元素的指针,而是指向数组本身的指针,这不是你想要的。

(一般来说,它可以工作,就像它显然对你所做的那样,但理论上它会调用未定义的行为,因为传入的表达式的实际类型和%s转换说明符所期望的类型不匹配。)

本文档是有关数组和指针的好读物,请务必阅读并理解它。

于 2013-07-06T06:43:44.630 回答
2

您正在使用数组。不要使用&whilescanf输入到数组

例如:scanf("%s",first);

数组已经通过引用传递。您不需要将&数组作为指向 C 中第一个元素的指针传递

于 2013-07-06T06:34:46.337 回答
1

尝试更改scanf("%s",&first);scanf("%s",first);(以及 的相似性last)。

在正常情况下(包括这些),数组的名称计算为数组中第一个元素的地址。在这种情况下,这是一个指向 char 的指针,这是转换所scanf期望的类型%s

&on 开头,您将获得相同的指针(即相同的地址),但作为指向数组的指针而不是指向数组元素的指针。由于这与 预期的类型不匹配%s,因此结果是未定义的行为(尽管由于它是正确的地址,这通常适用于大多数典型的编译器/CPU)。

于 2013-07-06T06:34:55.773 回答
1

scanf语句中删除 &。

scanf("%s", first);  // first is pointer to start of first
scanf("%s", last);   // last is pointer to start of last 

在 C 中,数组的名称是指向数组开头的指针。

格式参数后scanf需要指针参数或参数。

scanf(  "%s", first  );
scanf format-arg input-args

例如,如果将整数参数用于scanf,则需要 &(获取地址)运算符。

int n;
scanf("%d", &n);    // &n is pointer to n
于 2013-07-06T06:41:20.433 回答
0

scanf 需要一个地址,但是 char 数组 [] 已经是一个地址,而 scanf 不需要参考符号 & 因为名称本身就是一个地址

于 2013-07-06T06:36:48.093 回答