6

为什么在scanf函数中需要和号 (&)。以下 C 代码中的输出或错误类型(编译或运行时)是什么?

#include <stdio.h>

void main() {
    int a;
    printf("enter integer:");
    scanf("%d", a);
}
4

7 回答 7

12

C 中的&in C 是返回操作数地址的运算符。这样想,如果你只是简单地给出没有scanf的变量,它将按值传递给它,这意味着将无法设置它的值供你查看。通过引用传递它(实际上使用传递一个指向 的指针)允许对其进行设置,以便调用函数也能看到变化。a&scanf&ascanf

关于具体的错误,你真的说不出来。行为未定义。有时,它可能会默默地继续运行,而您却不知道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
于 2010-01-14T07:01:13.773 回答
3

在 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&xfoo*bar*bar = *bar + 1x = 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 *"
  ...
}
于 2010-01-14T15:25:30.933 回答
2

如果您要问这样的问题,我建议您现在只学习“它就是这样”。

您将了解到您需要一个 & 符号,因为scanf它需要一个或多个指针参数。如果 a 是 int 变量,则它不是指针。&a (“a 的地址”)是一个指针,所以它可以与scanf.

于 2010-01-14T07:01:57.907 回答
2

这是因为在 C 中,函数参数是按值传递的。为了让scanf()函数修改amain() 函数中的 ' ' 变量,应将 ' ' 的地址提供给,因此使用与号(地址)。ascanf()

于 2010-01-14T07:05:24.603 回答
1

因为scanf需要一个指向该值将进入的变量(即引用)的指针。

于 2010-01-14T07:00:14.177 回答
1

您并不总是需要使用&with scanf。您需要做的是传递指针。如果您是 C 新手,您应该花一些时间阅读 comp.lang.c 常见问题解答:

http://c-faq.com/

具体来说:

于 2010-01-14T07:18:31.597 回答
0

'&' inscanf仅用于获取变量的地址。您可以使用scanf指针不使用“&”:

int myInt;
int * pointer_to_int;
pointer_to_int = &myInt;
scanf("%d", pointer_to_int);

一般来说,使用“&”通常比创建指针来避免使用“&”更容易。

于 2010-01-14T21:03:03.510 回答