在我正在阅读的一本书中,C从头开始,在第113页上,编写者创建了一个char数组:
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]不需要被解除引用?
3 回答
假设,通过这个,你实际上意味着
p1
被声明并初始化使用;那么你的解释是错误的 .
p1
是指向char
的指针,而不是指向数组的指针 .在此定义中,
myString
是(先前在您的问题中声明的)char
数组的名称 . 在初始化中名称
myString
被转换为指针 . 该指针的值为&myString[0]
(即myString
中第一个字符的地址) . 这是p1
将获得的 Value .该声明
然后将
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)
.Note: 如果
*(p1[4])='c'
在您的代码中有效,那么p1[4] = 'c'
将无效,这表明我对p1
的声明和初始化的假设是正确的 - 尽管您已经省略了这些信息 .p1 + 4
将是4个以上的内存地址 .表达式
p1[4]
(完全等同于*(p1+4)
)称为左值表达式 . 我们说左值表达式指定一个内存位置 . 或者换句话说,左值表达式与内存位置本身是同义的 . 您始终可以在左值表达式上使用&
address-of运算符,并为您提供指向内存位置的指针 .左值表达式将继续以三种可能的方式之一使用:
将值存储在指定的内存位置,或
从指定的内存位置检索值,或
这些都没有 .
没有特殊的语法来区分这三种情况;相反,它取决于左值表达式所属的较大表达式 . 例如,应用
&
运算符是情况3;出现在赋值运算符=
左侧的是大小写1.大多数其他用法属于情况2 .p1[4]
被视为*(p1 + 4)
,即"value at an offset of 4 from p1" .当你声明一个char数组时:
myString是一个指向数组的指针(它指向第一个元素) . 所以,当你做
myString[4]
时,它也被视为*(myString + 4)
写
*(p1[4])
意味着*(*(p1 + 4))