首先是C:错误?指针语法

时间:2017-04-28 16:41:04

标签: c arrays pointers syntax assignment-operator

我正在自学C编程,使用" Head First C",由O&#Re;出版。 (还有其他一些文本。)

在本书的第58页示例程序中,我在本书的指针介绍中非常困惑。扔给我的是文中的一个小小的召唤,指着这条线:

int *choice = contestants;

标注为:

  

“选择”现在是“参赛者”阵列的地址。

据我所知,这是错误的。该行将*choice分配给存储为contestants数组的,是不是这样?

6 个答案:

答案 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)

严格来说,这本书不正确,但你的推理也是不正确的。

假设contestantsint的数组,则初始化

 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)),则代码将进行编译,并且转换后的值将相等。