我正在自学C编程,使用" Head First C",由O&#Re;出版。 (还有其他一些文本。)
在本书的第58页示例程序中,我在本书的指针介绍中非常困惑。扔给我的是文中的一个小小的召唤,指着这条线:
int *choice = contestants;
标注为:
“选择”现在是“参赛者”阵列的地址。
据我所知,这是错误的。该行将*choice
分配给存储为contestants
数组的值,是不是这样?
答案 0 :(得分:1)
免责声明:我现在无法访问该书/章。
考虑contestants
是数组类型,引用C11
,章节§6.3.2.1(强调我的)
除非它是
sizeof
运算符,_Alignof
运算符或者&
运算符的操作数。 一元contestants
运算符,或者是用于初始化数组的字符串文字,一个表达式 type ''类型''的数组被转换为类型''指向类型''指针的表达式 到数组对象的初始元素并且不是左值。 [...]
在您的情况下,数组变量用作赋值运算符的RHS,因此在这种情况下&(contestants[0])
与int *
相同。
这是与:before
完全相同的类型,它与要分配的变量(LHS)相同。
答案 1 :(得分:0)
您可能不知道的是,数组的名称是此数组的第一个元素上的指针。示例
int contestants[] = {1, 2, 3};
表示&contestants[0]
的值与contestants
答案 2 :(得分:0)
本章前面的 BULLET POINTS 列表对此进行了解释。
- 数组变量可用作指针。
- 数组变量指向数组中的第一个元素。
还在标有 POINTER DECAY 的方框中进一步向下:
因为数组变量与指针变量略有不同,所以在为指针分配数组时需要小心。如果将数组赋给指针变量,则指针变量将仅包含数组的地址。
答案 3 :(得分:0)
这本书是对的。指针与变量的工作方式不同,*在不同情况下的工作方式不同。
首先,您可能知道指针只是一个变量,其中包含另一个项目内存中的位置地址
当我们使用时
int *choice
我们创建一个指向整数的指针,该整数存储整数的地址
在这种情况下,我假设参赛者是一个阵列。我们假设它是一系列的整数
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的整数,因为存储的地址指向第一个元素
答案 4 :(得分:0)
所以你已经有了四个答案,但没有一个提到赋值和初始化语法之间的区别。
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
不包含地址,除非你初始化它。取消引用可能未初始化的指针总是一个错误。
答案 5 :(得分:0)
严格来说,这本书不正确,但你的推理也是不正确的。
假设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)
),则代码将进行编译,并且转换后的值将相等。