scanf使用指向变量的指针,而不是变量本身的指针

时间:2018-10-20 01:25:12

标签: c

我正在阅读有关指针The GNU C Programming Tutorial的“ GNU C编程”

它指出:

  

但是,scanf使用指向变量的指针,而不是变量本身的指针。例如,以下代码从键盘读取一个整数:

int my_integer;
scanf ("%d", &my_integer);

理解“变量”和“变量本身”令人困惑不解。
您能提供任何提示吗?

2 个答案:

答案 0 :(得分:5)

这令人困惑。也许更清楚的表达方式是scanf需要知道将要读取的值放在何处。为它提供变量的当前值不会有任何好处(除非该变量包含地址)您想要放置值)。

int my_integer;
scanf ("%d", &my_integer);

这会将scanf的值存储到my_integer的地址。如果没有&,您将向其传递my_integer的值,因为该变量尚未初始化,这将是垃圾。

“不是变量本身”这句话令人困惑。也许“不是值本身”会更有用,因为有时变量确实包含指向值存储位置的指针。

答案 1 :(得分:1)

此处起作用的规则是2018 C标准中的第6.3.2.1条第2款(以及早期标准中的相同或相似条款)。该规则告诉我们名称何时表示对象以及何时将其转换为值(因此不能再用于访问对象)。

变量实际上是两件事情:一个对象,它是一个存储区域(char的一个字节,int的几个字节,结构或数组的多个字节)和一个标识符(它的名字)。

在源代码中使用名称时,它是一个 lvalue ,它指定一个对象。 1,2 。条款6.3.2.1第2段告诉我们,当 lvalue 与一元&一起使用时,它转换为值。它指定对象,然后&运算符可以提供该对象的地址。

此段还告诉我们,当将左值与sizeof++--一起使用时,或者当它是{{1}的左操作数时,将不执行此转换。 }(用于访问结构)或.(用于分配)。

否则,将左值转换为它的值。 3

因此,在=中,scanf("%d", my_integer)被转换为其中的值。仅将此值传递给my_integer,因此scanf无法访问该对象。当您编写scanf时,scanf("%d", &my_integer)将使用&的地址,并将该地址传递到my_integer。这为scanf提供了一种访问对象的方法(通过其地址)。

表达式中使用的标识符不是C中唯一的左值。另一个常见的左值是表达式scanf,其中*p是指针。这是一个左值,实际上与使用p所指向的对象的名称相同。 4

注释

1 术语“左值”来自其在表达式左侧的历史外观,如p中所示。由于a = 3被分配更改,因此名称“ a”必须提供对对象的访问。它不能只是一个值。

2 C标准说,一个左值可能指定一个对象,但是在这里我们不需要考虑异常。

3 另外,如果左值指定数组,则不会将其转换为它的值。但是,在大多数情况下会执行不同的转换。数组将转换为指向其第一个元素的指针。

4 其他左值是字符串文字,对结构成员的引用(例如as.member)以及复合文字。左值还可以“通过”某些其他运算符,例如括号或p->member

相关问题