首页 文章

这个例子不应该改变内存地址而不是内存地址的值吗?

提问于
浏览
0

在我正在阅读的一本书中,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 回答

  • 0

    然后他创建了一个指向数组的指针:* p1 = myString;

    假设,通过这个,你实际上意味着 p1 被声明并初始化使用;

    char *p1 = myString;
    

    那么你的解释是错误的 . p1 是指向 char 的指针,而不是指向数组的指针 .

    在此定义中, myString 是(先前在您的问题中声明的) char 数组的名称 . 在初始化中

    char *p1 = myString;
    

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

    该声明

    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) .

    Note: 如果 *(p1[4])='c' 在您的代码中有效,那么 p1[4] = 'c' 将无效,这表明我对 p1 的声明和初始化的假设是正确的 - 尽管您已经省略了这些信息 .

  • 3

    p1 + 4 将是4个以上的内存地址 .

    表达式 p1[4] (完全等同于 *(p1+4) )称为左值表达式 . 我们说左值表达式指定一个内存位置 . 或者换句话说,左值表达式与内存位置本身是同义的 . 您始终可以在左值表达式上使用 & address-of运算符,并为您提供指向内存位置的指针 .

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

    • 将值存储在指定的内存位置,或

    • 从指定的内存位置检索值,或

    • 这些都没有 .

    没有特殊的语法来区分这三种情况;相反,它取决于左值表达式所属的较大表达式 . 例如,应用 & 运算符是情况3;出现在赋值运算符 = 左侧的是大小写1.大多数其他用法属于情况2 .

  • -3

    p1[4] 被视为 *(p1 + 4) ,即"value at an offset of 4 from p1" .

    当你声明一个char数组时:

    myString[80]
    

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

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

相关问题