C语言中的scanf函数是如何工作的?

发布于 2024-08-17 15:19:24 字数 204 浏览 3 评论 0原文

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

#include <stdio.h>

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

Why do you require ampersand (&) in the scanf function. What will the output or type of error (compile or runtime) be in the following C code?

#include <stdio.h>

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

你げ笑在眉眼 2024-08-24 15:19:25

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

The & in C is an operator that returns the address of the operand. Think of it this way, if you would simply give scanf the variable a without the &, it will be passed to it by-value, which means scanf will not be able to set its value for you to see. Passing it by-reference (using & actually passes a pointer to a) allows scanf to set it so that the calling functions will see the change too.

Regarding the specific error, you can't really tell. The behavior is undefined. Sometimes, it might silently continue to run, without you knowing scanf changed some value somewhere in your program. Sometimes it will cause the program to crash immediately, like in this case:

#include <stdio.h>
int main()
{
    int a;
    printf("enter integer: ");
    scanf("%d",a);
    printf("entered integer: %d\n", a);
    return 0;
}

Compiling it shows this:

$ 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’

And executing shows a segmentation fault:

$ ./test 
enter integer: 2
Segmentation fault
变身佩奇 2024-08-24 15:19:25

在 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地址(由表达式 &x 给出)调用 foo),而不是 x 中包含的值。表达式*bar的意思是“获取位置栏中指向的值”,因此*bar = *bar + 1对应于x = x + 1

由于 scanf() 需要写入其参数,因此它希望这些参数类型化为指针。 “%d”转换说明符期望相应的参数是指向 int 的指针 (int *),“%u”转换说明符期望相应的参数是指向 unsigned int 的指针 (unsigned *) code>),“%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 *"
  ...
}

In C, all function arguments are passed by value; any changes to the function's formal parameter are not reflected in the actual parameter. For example:

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;
}

The output of the program will be

x before foo = 0
x after foo = 0

because bar receives the value of x (0), not a reference to x itself. Changing bar has no effect on x.

In C, the way around this is to pass a pointer to a variable:

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;
}

Now the output of the program is

x before foo = 0
x after foo = 1

This time, the formal parameter bar is not an int, but a pointer to int, and it receives the address of x (given by the expression &x in the call to foo), not the value contained in x. The expression *bar means "get the value in the location bar points to", so *bar = *bar + 1 corresponds to x = x + 1.

Since scanf() needs to write to its arguments, it expects those arguments to typed as pointers. The "%d" conversion specifier expects the corresponding argument to be a pointer to int (int *), the "%u" conversion specifier expects a pointer to unsigned int (unsigned *), "%s" expects a pointer to char (char *), "%f" expects a pointer to float (float *), etc. In your example, since a is typed int, you need to use the expression &a to get a pointer.

Note that if a were already a pointer type, you would not need to use the & operator in the call to 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
  ...
}

Note also that when passing an array to a function (such as when using the "%s" conversion specifier to read a string), you don't need to use the & operator; the array expression will implicitly be converted to a pointer type:

int main(void)
{
  char name[20];
  ...
  scanf("%19s", name); // name implicitly converted from "char [20]" to "char *"
  ...
}
扎心 2024-08-24 15:19:25

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

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

If you're asking a question like this, I would recommend just learning for now "it just does".

You will learn that you need an ampersand because scanf takes one or more pointer arguments. If a is an int variable, it is not a pointer. &a ("the address of a") is a pointer, so it will work with scanf.

请止步禁区 2024-08-24 15:19:25

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

This is because in C, functions parameters are passed by value. In order for the scanf() function to modify the 'a' variable in your main() function, the address of 'a' shall be given to scanf(), hence the usage of the ampersand (address of).

无风消散 2024-08-24 15:19:25

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

Because scanf requires a pointer to the variable (i.e. a reference) that the value will go into.

深府石板幽径 2024-08-24 15:19:25

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

http://c -faq.com/

具体来说:

You don't always need to use an & with scanf. What you need to do is to pass pointers. If you're new to C, you should spend some time reading the comp.lang.c FAQ:

http://c-faq.com/

Specifically:

入画浅相思 2024-08-24 15:19:25

'&' scanf 中只需要获取变量的地址。您可以使用不带“&”的scanf通过使用指针:

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

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

The '&' in scanf is only required to get the address of a variable. You can use scanf without '&' by using pointers:

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

In general, using '&' is often easier than creating pointer to avoid using the '&'.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文