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 T
的pointer 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。