在下面的代码中,有人可以解释为什么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"直接访问该值。它被添加到"总和"中