在 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的地址(由在对foo 的调用中表达&x),而不是x 中包含的值。表达式*bar 的意思是“获取位置栏中的值指向”,所以*bar = *bar + 1 对应于x = x + 1。
由于scanf() 需要写入其参数,因此它希望将这些参数键入为指针。 "%d" 转换说明符期望对应的参数是一个指向 int (int *) 的指针,"%u" 转换说明符期望一个指向 unsigned int (unsigned *) 的指针,"%s" 期望一个指向char (char *), "%f" 需要一个指向 float (float *) 的指针,等等。在您的示例中,由于 a 的类型为 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 *"
...
}