在我正在阅读的一本书中,C++从头开始,在第 113 页上,作者创建了一个字符数组:
myString[80];
然后他使用一个函数来复制一些 charectars:
strcpy(myString,"Hello there");
然后他创建一个指向数组的指针:
*p1 = myString;
然后他使用偏移量并在该偏移量处断言一个值:
p1[4]='c';
我的问题是,P1 是一个指针,所以它是一个内存地址,而 4 的偏移量给了他前面 4 个空格的内存地址,所以这意味着他将字母"c"断言到内存地址而不是存储在该地址的值。不应该是:
*(p1[4])='c';
基本上,为什么 *(P1 + 4( 需要取消引用,而 P1[4] 不需要?
我试图理解这一点,唯一对我来说有意义的事情是方括号是否充当星号来取消引用指针。这是正确的还是有其他原因为什么p1[4]不需要取消引用?
然后他创建一个指向数组的指针:
*p1 = myString;
假设,你的意思是p1
是用 声明和初始化的;
char *p1 = myString;
那么你的解释是错误的。p1
是指向char
的指针,而不是指向数组的指针。
在此定义中,myString
是(之前在您的问题中声明的(char
数组的名称。 在初始化中
char *p1 = myString;
名称myString
将转换为指针。 该指针将具有值&myString[0]
(即myString
中第一个字符的地址(。 这就是p1
将获得的价值。
声明
p1[4] = 'c';
然后将myString
的第五个字符(因为索引从零开始(设置为'c'
。 因此,结果是myString[4]
更改为值'c'
。 这意味着(前 11 个字符(myString
将被"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)
(称为左值表达式。 我们说左值表达式指定一个内存位置。 换句话说,左值表达式是内存位置本身的同义词。 您始终可以在 lvalue 表达式上使用&
address-of 运算符,这将为您提供指向内存位置的指针。
左值表达式将继续以以下三种可能的方式之一使用:
- 将值存储在指定的内存位置,或
- 从指定的内存位置检索值,或
- 都不是。
没有特殊的语法来区分这三种情况;相反,它取决于左值表达式所属的较大表达式。 例如,应用&
运算符是情况 3; 出现在赋值运算符=
左侧的是情况 1。 大多数其他用法属于情况 2。
p1[4]
被视为*(p1 + 4)
,即"与 p1 偏移量为 4 的值"。
同样,当您声明字符数组时:
myString[80]
myString 是指向数组的指针(它指向第一个元素(。因此,当您执行myString[4]
时,它也被视为*(myString + 4)
写*(p1[4])
意味着*(*(p1 + 4))