scanf()的行为

可能重复:
scanf()与&运算符混淆

为什么我们需要一个&in scanf来输入整数,为什么不输入字符。 在输入时,&scanf指的是merory位置。

例如:-

main() { int a; char c; scanf("%d",&a); scanf("%c"c); } 

对于每个转换说明符, scanf()期望相应的参数是指向正确类型的指针: %d期望类型为int *的参数, %f期望类型为double *%c%s的参数都期望参数char *等类型

%c%s之间的区别在于前者告诉scanf()读取单个字符并将其存储在相应参数指定的位置,而后者告诉scanf()读取多个字符,直到它看到0-值字符并将所有这些字符存储在缓冲区中,从参数指定的位置开始。

如果它们不是指针类型,则需要在参数上使用&运算符。 例如:

 int x; int *px = some_valid_memory_location_such_as_&x; char c; char *pc = some_valid_memory_location_such_as_&c; ... scanf("%d", &x); // x is not a pointer type, so we must use the & operator scanf("%d", px); // px is a pointer type, so we don't need the & operator scanf("%c", &c); // etc. scanf("%c", pc); // etc. 

令人困惑的地方是读取字符串 (使用%s转换说明符):

 char buf[SIZE]; scanf("%s", buf); // expression 'buf' *implicitly* converted to pointer type 

在这种情况下,为什么我们不需要&运算符? 它与C如何处理数组表达式有关。 当编译器看到数组类型的表达式(例如scanf()调用中的buf )时,它会隐式地将表达式从N-element array of T类型N-element array of T转换为pointer to T N-element array of Tpointer to T ,并将其值设置为第一个的地址数组中的元素。 这个值不是左值 – 它不能分配给(因此你不能写像buf = foo这样的东西)。 此规则的唯一例外是当数组表达式是sizeof&运算符的操作数时,或者数组表达式是用于初始化另一个数组的字符串文字时:

 char *p = "This is a test"; // string literal implicitly converted to char *, // string *address* written to p char a[] = "This is a test"; // string literal not implicitly converted, // string *contents* copied to a 

简而言之,表达式buf 隐式地char [SIZE]类型转换为char * ,因此我们不需要使用&运算符,实际上表达式&buf的类型将是pointer to SIZE-element array of char ,或(*)[SIZE] ,这不是scanf()期望的%s转换说明符。

两种情况都需要符号符号。 scanf需要指针(你可能会想到char *或char [] – 它们本身就是指针)。

Scanf将输入读取到存储器地址a是a所持有的价值。 &a是内存中的位置。

在上面的代码中, c应该是&c

因为scanf()需要指针,而&a是指向整数的指针。

在您的示例中,您需要在c前面使用逗号和&符号。

 int main(void) { int a; char c; char s[21]; scanf("%d",&a); scanf("%c", &c); // Fixed! scanf("%20s", s); printf("a = %d, c = %c, s = <<%s>>\n", a, c, s); } 

如果您正在读取字符串,则将字符串 – 指向char的指针 – 传递给scanf()

你需要提供带有指针的scanf ,这就是你在scanf中使用的原因(“%d”,&a) ; 。 scanf(“%c”c) ; 根本不会工作。

你的榜样是错的。 如果你有

 char c; 

然后你需要在调用scanf时添加一个&到名称:

 scanf("%c", &c); 

但是 ,如果你的变量已经是一个指针,例如因为它是一个char[] (这是指针的一种奇特的语法),你必须省略&

我喜欢将&符号(&)视为“地址”。 所以你读&a作为“地址”。

另外,我尝试编译这个,但它在gcc上警告我:

 Warning: format "%c" expects type 'char *', but argument 2 has type 'int' 

这是真的,因为char基本上是一个int。