scanf() 需要一个指针作为参数,但 printf 不需要。printf 只需要变量的名称,它似乎以某种方式获得了存储在变量内存位置的值。为什么不通过将变量名称解析到内存位置(与 printf 的工作方式相同)并将值存储在其中来使 scanf 以相同的方式运行?
- printf("%d",&var) 和 printf("%d",var) 有什么区别
- printf("%p",&var) 和 printf("%p",var) 有什么区别
C 是一种按值传递的语言。如果你要写:
int x;
scanf("%d", x);
scanf
将不知道将扫描结果放在哪里 - 您需要将指针传递给存储扫描值的内存位置:
scanf("%d", &x);
如果这有助于您理解它,您还可以创建一个显式指针变量:
int *y = &x;
scanf("%d", y);
相反,printf
不关心值的位置,只关心值恰好是什么。所以传递值:
printf("%d", x);
很好。至于您的具体问题(假设int var;
):
printf("%d",&var)
和有什么区别printf("%d",var)
严格来说,第一个会导致未定义的行为,第二个会打印 的值var
。在实践中,很多实现都会var
在第一种情况下打印地址。
printf("%p",&var)
和有什么区别printf("%p",var)
这种情况正好相反。第一个打印 的地址var
,第二个导致未定义的行为。在实践中,它可能会打印 的值var
,但您不应该依赖它。要真正正确,第一个也应该是printf("%p", (void *)&var);
,但是我从未见过您在那里编写的内容无法正常工作的实现。
在第一种情况下,您正在打印的地址var
。在第二种情况下, 的内容val
。
&val
是 的地址val
。
scanf
获取地址(指针)以获取值
您通过值将变量传递给 printf,这就是 printf 需要知道的所有内容,它只应该打印变量(或表达式)的值。但这对于 scanf 来说是不够的,它需要修改变量所占用的内存,您希望将数据从例如标准输入中读取。这就是为什么 scanf 需要变量占用的内存地址的原因——没有其他方法可以修改变量。
因为scanf()
需要修改它的论点。而且,由于在 C 中,参数没有“按引用传递”语义,只有按值传递(这本质上意味着每个参数的值在传递给函数时被复制),因此,只能使用指针来让函数修改它们的参数。
printf("%d", &var)
和 和有什么不一样printf("%d", var)
?
第一个总是调用未定义的行为,第二个不会 if var
is an int
, short
or char
。
printf("%p", &var)
和 和有什么不一样printf("%p", var)
?
第一个总是调用未定义的行为,第二个不会 if var
is a void *
。