数组索引和指针运算#
数组索引和指针运算都会根据元素的类型宽度进行调整。数组索引语法在 C 编译器内部也会自动转换成指针运算。
数组索引#
数组索引会根据数据大小自动调整位置,地址值实际增加 index * sizeof(<typename>)
。
int arr[] = {101, 102, 103};
printf("\d", arr[1]); // 102
printf("\d", arr[2]); // 103
arr[0] arr[1] arr[2]
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┐
│ │ │ 101 │ 102 │ 103 │ │ │
└─────┴─────┴─────┴─────┴─────┴─────┴─────┘
low 0xe364 0xe368 0xe36c high
指针运算#
指针的加减运算并不是以字节为单位,而是以数据类型的宽度,地址值实际增加 n * sizeof(<typename>)
。
int arr[] = {101, 102, 103};
int* p = arr;
int* p1 = p + 1;
int* p2 = p + 2;
int offset = p2 - p; // 2
*p *p1 *p2 p p1 p2
┌─────┬─────┬─────┬─────┬─────────┬──────────┬──────────┐
│ │ 101 │ 102 │ 103 │ 0xe364 │ 0xe368 │ 0xe36c │
└─────┴─────┴─────┴─────┴─────────┴──────────┴──────────┘
low 0xe364 0xe368 0xe36c high
为什么指针能够判断数据类型宽度?
虽然在语法上,我们没有明确指定指针加减的类型宽度,但是这一切都是由 C 编译器内部确定的。
在编译时,C 会先计算不同数据类型的宽度,然后再对指针进行合适的偏移操作,例如:
arr + i * sizeof(long)
编译器行为#
数组索引语法在 C 编译器内部会自动转换成指针运算:
char* str = "apple";
char thirdLetter = str[2];
// the same
char thirdLetter = *(str + 2);