为什么在scanf
函数中需要和号 (&)。以下 C 代码中的输出或错误类型(编译或运行时)是什么?
#include <stdio.h>
void main() {
int a;
printf("enter integer:");
scanf("%d", a);
}
C 中的&
in C 是返回操作数地址的运算符。这样想,如果你只是简单地给出没有scanf
的变量,它将按值传递给它,这意味着将无法设置它的值供你查看。通过引用传递它(实际上使用传递一个指向 的指针)允许对其进行设置,以便调用函数也能看到变化。a
&
scanf
&
a
scanf
关于具体的错误,你真的说不出来。行为未定义。有时,它可能会默默地继续运行,而您却不知道scanf
程序中某处的某些值发生了变化。有时它会导致程序立即崩溃,比如这种情况:
#include <stdio.h>
int main()
{
int a;
printf("enter integer: ");
scanf("%d",a);
printf("entered integer: %d\n", a);
return 0;
}
编译它显示了这一点:
$ gcc -o test test.c
test.c: In function ‘main’:
test.c:6: warning: format ‘%d’ expects type ‘int *’, but argument 2 has type ‘int’
并执行显示分段错误:
$ ./test
enter integer: 2
Segmentation fault
在 C 中,所有函数参数都是按值传递的;对函数形式参数的任何更改都不会反映在实际参数中。例如:
void foo(int bar)
{
bar = bar + 1;
}
int main(void)
{
int x = 0;
printf("x before foo = %d\n", x);
foo(x);
printf("x after foo = %d\n", x);
return 0;
}
该程序的输出将是
x 之前的 foo = 0 foo = 0 之后的 x
因为bar
接收到x
(0) 的值,而不是对x
自身的引用。更改bar
对 没有影响x
。
在 C 中,解决此问题的方法是将指针传递给变量:
void foo(int *bar)
{
*bar = *bar + 1;
}
int main(void)
{
int x = 0;
printf("x before foo = %d\n", x);
foo(&x);
printf("x after foo = %d\n", x);
return 0;
}
现在程序的输出是
x 之前的 foo = 0 foo = 1 之后的 x
这一次,形参bar
不是一个 int,而是一个指向int 的指针,它接收的是(由对的调用中的表达式给出)的地址,而不是 x 中包含的值。该表达式的意思是“获取位置栏中指向的值”,因此对应于。 x
&x
foo
*bar
*bar = *bar + 1
x = x + 1
由于scanf()
需要写入其参数,因此它期望将这些参数键入为指针。"%d" 转换说明符期望对应的参数是一个指向 int ( int *
) 的指针,"%u" 转换说明符期望一个指向 unsigned int ( unsigned *
) 的指针,"%s" 期望一个指向 char ( char *
) 的指针,"% f" 需要一个指向 float ( float *
) 等的指针。在您的示例中,由于a
是 typed int
,您需要使用表达式&a
来获取指针。
请注意,如果a
已经是指针类型,则不需要&
在调用中使用运算符scanf()
:
int main(void)
{
int a, *pa; // declare pa as a pointer to int
...
pa = &a; // assign address of a to pa
scanf("%d", pa); // scanf() will write to a through pa
...
}
另请注意,将数组传递给函数时(例如使用“%s”转换说明符读取字符串时),您不需要使用&
运算符;数组表达式将隐式转换为指针类型:
int main(void)
{
char name[20];
...
scanf("%19s", name); // name implicitly converted from "char [20]" to "char *"
...
}
如果您要问这样的问题,我建议您现在只学习“它就是这样”。
您将了解到您需要一个 & 符号,因为scanf
它需要一个或多个指针参数。如果 a 是 int 变量,则它不是指针。&a (“a 的地址”)是一个指针,所以它可以与scanf
.
这是因为在 C 中,函数参数是按值传递的。为了让scanf()
函数修改a
main() 函数中的 ' ' 变量,应将 ' ' 的地址提供给,因此使用与号(地址)。a
scanf()
因为scanf
需要一个指向该值将进入的变量(即引用)的指针。
您并不总是需要使用&
with scanf
。您需要做的是传递指针。如果您是 C 新手,您应该花一些时间阅读 comp.lang.c 常见问题解答:
具体来说:
'&' inscanf
仅用于获取变量的地址。您可以使用scanf
指针不使用“&”:
int myInt;
int * pointer_to_int;
pointer_to_int = &myInt;
scanf("%d", pointer_to_int);
一般来说,使用“&”通常比创建指针来避免使用“&”更容易。