我正在教自己C编程,使用O'Reilly出版的" Head First C"。(此外,还有其他几本文本。(
在第58页上的示例节目中,我在这本书的指针介绍中非常挂起。给我扔的是文字中有点呼唤,指向这条线:
int *choice = contestants;
呼叫读数:
"选择"现在是"参赛者"数组的地址。
,据我所知,这是错误的。该行将*choice
分配给存储为contestants
数组的 value ,不是吗?免责声明:我现在无法访问本书/章节。
考虑contestants
是数组类型,引用C11
,第§6.3.2.1章(强调矿山((
除非是
sizeof
操作员的操作数,_Alignof
操作员或 Unary&
操作员,或者是用于初始化数组的字符串,表达式具有 类型''type'数组'被转换为带有类型'指针的'指点'的表达式 对于数组对象的初始元素,而不是lvalue。[...]
在您的情况下,数组变量用作分配运算符的RHS,因此在这种情况下,contestants
与&(contestants[0])
相同。
这是int *
完全相同的类型,它是要分配的变量的相同类型(LHS(。
,因此您已经有四个答案,但他们都没有提到 sigitionment 和初始化语法之间的区别语法。
int *choice = contestants; // initialization
以上等效于此:
int *choice; // declaration
choice = contestants; // assignment to pointer
,但与此完全不同(在初始化中无法完成(:
int *choice; // declaration
*choice = contestants; // assignment to target (not valid unless choice is initialized)
第二版本不正确,因为它试图将contestants
的值存储在choice
指向的地址上 - 但是choice
不包含地址,除非您初始化。取消可能的统一指针始终是一个错误。
这本书是正确的。指针的工作方式与变量不同, *在不同情况下的工作方式不同。
开始,您可能知道指针只是一个变量,该变量包含位置的地址,以存储另一个项目
我们使用 int *choice
我们创建一个指向整数的指针,该密码存储整数的地址
在这种情况下,我假设参赛者是一个数组。我们假设这是一个ints
int contestants[5] = [0,1,2,3,4];
集合(例如数组(总是存储为指向第一个元素的指针。因此,第二个元素是addressof_first_item + sizeof(element_stored)
。
让我们假设地址是0x12345
,就像此int contestants = 0x12345
现在我们选择了该地址: int *choice = contestants
换句话说,这是通往整数的指针,恰好是参赛者数组中的第一个元素。
作为旁注,我们也可以将其写为:
int* choice = &contestants[0];
*操作员的另一个用例在指针方面是删除。提取涉及将值在指向指向的地址上获取值。
int value = *choice;
将为我们提供一个值为0的整数,因为地址存储到第一个元素
您可能不知道的是数组的名称是该数组的第一个元素上的指针。示例
int contestants[] = {1, 2, 3};
表示&contestants[0]
具有与contestants
的值相同的值列表。
- 一个数组变量可以用作指针。
- 数组变量指向数组中的第一个元素。
以及在标有指针decay 的框中进一步向下。
由于数组变量与指针变量略有不同,因此当将数组分配给指针时,您需要小心。如果将数组分配给指针变量,则指针变量仅包含数组的地址。
严格来说,这本书不正确,但是您的推理也不正确。
假设contestants
是int
的数组,初始化
int *choice = contestants;
等于
int *choice = &contestants[0];
换句话说,choice
的值是contestants
的第一个元素的地址。contestants
(数组的名称(转换为&contestants[0]
(指针(通常称为"指针阵列"转换。
但是,由于类型是错误的,这与contestants
数组的地址不同。contestants
数组的地址是&contestants
,它具有int (*)[4]
类型(即四个int的数组的地址(。
如果您尝试初始化
int *choice = &contestants;
结果将是汇编错误(因为int(*)[4]
不能隐式转换为int *
(。
您的推理
,据我所知,这是错误的。该行分配 *选择为存储为参赛者数组的值,不是吗?
有缺陷,因为contestants
没有存储值。这是一组值。
确实,&contestants[0]
和&contestants
具有相同的值,但它们的类型也不同。因此&contestant[0] == &contestants
的比较不会编译。但是,如果将值转换为通用类型,例如(void *)(&contestants[0]) == (void *)(&contestants)
,则代码将编译,并且转换值将比较相等。