关于C++:这个例子不应该改变内存地址而不是内存地址的值吗?

should this example not alter the memory address rather than the value at that memory address?

在我正在阅读的一本书中,C++从零开始,在第113页,作者创建了一个字符数组:

1
myString[80];

然后他使用一个复制一些字符的函数:

1
strcpy(myString,"Hello there");

然后他创建一个指向数组的指针:

1
*p1 = myString;

然后他使用偏移量并在该偏移量处指定一个值:

1
p1[4]='c';

我的问题是,p1是一个指针,所以它是一个内存地址,4的偏移量给了他前面的内存地址4个空格,这意味着他将字母"c"分配到内存地址,而不是存储在该地址的值。不应该是:

1
*(p1[4])='c';

基本上,为什么*(p1+4)需要解引用,但p1[4]不需要解引用?

我试图理解这一点,唯一对我有意义的是,如果方括号充当星号来取消对指针的引用。这是正确的吗,还是有其他原因不需要取消对p1[4]的引用?


then he creates a pointer to the array:

1
*p1 = myString;

假设,通过这个,您实际上是指使用声明和初始化p1

1
char *p1 = myString;

那么你的解释就错了。p1是指向char的指针,而不是指向数组的指针。

在这个定义中,myStringchar数组的(以前在您的问题中声明的)名称。在初始化过程中

1
char *p1 = myString;

名称myString转换为指针。该指针的值为&myString[0](即myString中第一个字符的地址)。这是p1将得到的值。

声明

1
 p1[4] = 'c';

然后将myString的第五个字符(因为索引是从零开始)设置为'c'。因此,结果是将myString[4]改为'c'的值。这意味着(myString的前11个字符)将是"Hellc there"

假设上述情况,表达式*(p1[4])='c'将不会编译,因为(p1[4])char类型,并且不能使用*运算符取消引用。

在语义上,在表达式p1[4]中等价于*(p1 + 4)。由于p1初始化为等于&myString[0]p1[4]也等于myString[4]*(myString + 4)

注:如果*(p1[4])='c'在您的代码中是有效的,那么p1[4] = 'c'将无效,这表明我关于p1的声明和初始化的假设是正确的,尽管您忽略了这些信息。


p1 + 4将是内存地址之外的4个位置。

表达式p1[4](完全等同于*(p1+4))称为左值表达式。我们说一个左值表达式指定了一个内存位置。或者换句话说,左值表达式是内存位置本身的同义词。您总是可以在左值表达式上使用操作符的&地址,这会给您一个指向内存位置的指针。

左值表达式将继续以三种可能的方式之一使用:

  • 将值存储在指定的内存位置,或
  • 从指定的内存位置检索值,或
  • 两者都不是。
  • 这三种情况没有特殊的语法来区分;相反,它取决于左值表达式所属的较大表达式。例如,应用&运算符的情况是3;出现在赋值运算符=的左侧的情况是1。大多数其他用法属于案例2。


    p1[4]被视为*(p1 + 4),它是"从p1偏移4的值"。

    另外,当您声明一个char数组时:

    1
    myString[80]

    myString是指向数组的指针(它指向第一个元素)。所以当你做myString[4]时,它也被当作*(myString + 4)处理。

    *(p1[4])意味着*(*(p1 + 4))