2010-01-14 97 views
6

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

#include <stdio.h> 

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

顺便说一句,'main'返回'int',不'void'。 – 2010-01-14 15:31:10

回答

11

C中的&是一个返回操作数地址的运算符。想一想,如果你只是给scanf变量a没有&,它会通过值传递给它,这意味着scanf将无法​​为您设置其值。通过引用(使用&实际上传递指向a的指针)允许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 
1

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

2

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

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

2

这是因为在C中,函数参数是,通过值传递。为了使scanf()函数修改main()函数中的'a'变量,'a'的地址应赋予scanf(),因此使用“与”号(地址)。

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 before foo = 0 
x after foo = 0 

因为bar接收的x(0),而不是一个参考值来x本身。更改barx没有影响。

在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 before foo = 0 
x after foo = 1 

这一次,形参bar不是int,而是一个指针为int,并且它接收地址的x(由给定的在调用foo时表达式&x),而不是x中包含的值。表达*bar的意思是“在位置栏得到的值指向”,所以*bar = *bar + 1对应于x = x + 1

由于scanf()需要写入它的参数,它预计这些参数类型为指针。的“%d”转换指定期望对应的参数是一个指针到int(int *)中,“%u”的转换说明需要一个指向无符号整型(unsigned *),“%S”期望字符指针(char *) “%F”需要一个指向浮动(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 *" 
    ... 
} 
0

scanf的“&”只需要得到一个变量的地址。您可以通过使用指针使用scanf无“&”:

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

一般情况下,使用“&”往往比创建的指针,以避免使用“&”更容易。