我正在阅读有关指针The GNU C Programming Tutorial的“ GNU C编程”
它指出:
但是,scanf使用指向变量的指针,而不是变量本身的指针。例如,以下代码从键盘读取一个整数:
int my_integer;
scanf ("%d", &my_integer);
理解“变量”和“变量本身”令人困惑不解。
您能提供任何提示吗?
答案 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 其他左值是字符串文字,对结构成员的引用(例如a
或s.member
)以及复合文字。左值还可以“通过”某些其他运算符,例如括号或p->member
。