C - 了解指针取消引用和数组索引之间的区别



在下面的代码中,有人可以解释为什么sum += *(ptr+i);sum += ptr[i];相同吗?

我知道sum += *(ptr+i);取消引用内存地址,然后对数字求和?

但在sum += ptr[i];中,没有尊重...

#include <stdio.h>
#include <stdlib.h>
int main() {
    int len, i, sum;
    printf("Enter how many numbers you want to sum:");
    scanf("%d", &len);
    int* ptr;
    ptr = (int*)malloc(sizeof(int) * len);
    for(i=0; i < len; i++) {
        printf("Enter a number:");
        scanf("%d", ptr+i);
    }
    for(i=0; i < len; i++) {
    //sum += *(ptr+i);
      sum += ptr[i];    
    }
    printf("The sum is %d", sum);
    return 0;
}

根据定义(C 标准,6.5.2.1 数组下标(

2 后缀表达式后跟方括号中的表达式 [] 是数组对象的元素的下标指定。这 下标运算符 [] 的定义是 E1[E2] 与 (*((E1(+(E2(((。由于适用于 二进制 + 运算符,如果 E1 是数组对象(等效于指针 数组对象的初始元素(,E2 是一个整数, E1[E2] 表示 E1 的第 E2 元素(从零开始计数(。

因此这三句话

sum += *(ptr+i);
sum += ptr[i];    
sum += i[ptr];    

是等效的。

考虑到程序具有未定义的行为,因为变量sum未初始化:)为了避免溢出,最好将其声明为

long long int sum = 0;
// ...
printf("The sum is %lldn", sum);

这是一样的,因为这就是语言的工作方式。是的,[]索引运算符确实取消了对其左侧指针的引用,它必须这样做才能获取值。

在一般的C语言中,a[b]等同于*(a + b)

这导致了有趣的经典,如

printf("%cn", 4["foobar"]);

上面的打印a,因为*(4 + "foobar")*("foobar" + 4)相同,即 "foobar"[4] .

ptr[i]计算结果为*(ptr + i)实际增量取决于指针的类型

如果ptr int,则增量即ptr + 1会将地址递增4(假设int为4个字节(内存位置,即(如果ptr 0xFF000005 ptr+1将被0xFF000009(

如果ptr char,则增量即ptr + 1会将地址增加 1 个内存位置(如果ptr 0xFF000005 ptr+1将0xFF000006(

但在sum += ptr[i]没有尊重

只有在不使用取消引用运算符*的意义上,才没有取消引用。然而,取消引用仍然存在,因为 C 中的索引运算符 [] 等价于 *:两者在所有情况下都是完全可以互换的。当你看到x[i]时,你可以把它重写为*(x+i),反之亦然。

将加法的取消引用重写为索引表达式的能力导致了 C 语法中最不可读的结构之一 - 将x[i]重写为 i[x] 的能力。

sum += *(ptr+i);这里最初将索引值"i"添加到"ptr"中,然后在取消引用数组指针以获取值之后。它被添加到"总和"中

sum += ptr[i];这里通过数组"PTR"中的索引值"i"直接访问该值。它被添加到"总和"中

最新更新