scanf()(C语言)让我困惑

时间:2010-06-17 01:41:41

标签: c scanf

我何时需要在C中插入/不插入& scanf()?谢谢。

int main()
{
    char s1[81], s2[81], s3[81];

    scanf("%s%s%s", s1, s2, s3);

    // If replace scanf() with the expression below, it works too.
    // scanf("%s%s%s", &s1, &s2, &s3);

    printf("\ns1 = %s\ns2 = %s\ns3 = %s", s1, s2, s3);

    return 0;
}

//programming is fun
//
//s1 = programming
//s2 = is
//s3 = fun

9 个答案:

答案 0 :(得分:9)

scanf将扫描的值放在其参数指向的地址中。 &是地址运算符,它用于获取变量的地址。

但是,您正在使用数组,并且当用作函数参数时,数组会降级为指针。所以,你不需要使用&数组的运算符。

示例:

char s[81];
int n;
int* nptr;
//Initialize nptr to some meaningful value
scanf("%s %d %d",s,&n,nptr);

在这种情况下,我们需要使用&运营商得到的地址是n保留。我们不需要将它与nptr一起使用,因为它已经是指向内存中某个位置的指针,也不是s,因为当数组传递给函数时,数组会被降级为指针。

答案 1 :(得分:6)

格式说明符后面的参数必须是指针。将数组名称传递给函数时,将传递初始元素的位置,因此您的示例中根本不需要使用&。你可以这样做(来自K&R):

int day, year;
char monthname[20];

scanf("%d %s %d", &day, monthname, &year);

由于日期和年份为int,您必须使用&来获取这些变量的地址。由于monthname是一个数组,因此不需要&

答案 2 :(得分:4)

在C中,当您处理数组时:

int c_array[24];
c_array == &c_array == &c_array[0]

是的,它很有趣 - 它们看起来一样(区别在于类型)。阅读this

答案 3 :(得分:3)

来自comp.lang.c FAQ:I thought you always needed an & on each variable passed to scanf.

我强烈建议您阅读其余的comp.lang.c FAQ

答案 4 :(得分:2)

s1返回数组第一个元素的地址,而&s1返回数组本身的地址。第一个元素的地址和数组本身的地址是相同的,因此两个表示都可以工作。

答案 5 :(得分:1)

只是一个猜测,但我认为这是因为s1s2s3是数组。

答案 6 :(得分:1)

如果a是一个数组,则a&a都会在此上下文中生成指针:

  • a由于数组衰减为指针(C99,§6.3.2.1/ 3 )而导致:

      

    除非是sizeof运算符或一元&运算符的操作数。运算符,或者是用于初始化数组的字符串文字,具有类型''数组类型''的表达式将转换为类型为''指向类型'的指针的表达式,指向数组对象的初始元素并且不是左值。

    ...强调添加

  • &a作为&运算符的结果 - 它返回指向对象的指针。

答案 7 :(得分:1)

Scanf接受可变数量的参数。 scanf的第一个参数是格式,然后n表示要存储的值,而n是格式字符串中指定的格式数。因为您正在使用数组,所以要存储您必须提供数组基址的值。


//If int
int i;
scanf("%d",&i); // store int value at address &i

float f;
scanf("%f",&f); //store float value at address &f

int a[10];
scanf("%s",a); //store string or array value at a

如果在最后一行中使用a会让您感到困惑,您可以尝试使用第一个元素的地址进行相同的操作,即& a [0]。

希望它有所帮助,
GG

答案 8 :(得分:0)

通常,您可以像在未注释的行中那样使用scanf。 C数组的工作方式是s1,s2等数组的名称,而s3实际上是数组第一个元素的地址。但是对于任何基元,您必须使用& variable语法。例如:

float f;
scanf("%f", &f);