通过指针访问数组

Accessing array by pointers

本文关键字:数组 访问 指针      更新时间:2023-10-16

let int * ptr,array[10]; ptr= array; .现在,阵列连续位置中的每个存储单元都具有固定大小。如果第一个单元格的地址是 1234,则下一个单元格必须位于 1238 地址。但是我们使用指针访问它 *(ptr+1) .我对此感到困惑。任何来源或答案?谢谢。

来自 C11 标准:§6.5.2.1

后缀表达式后跟方括号 [] 中的表达式是下标 数组对象的元素的指定。下标运算符 [] 的定义 是 E1[E2] 与 (*((E1(+(E2(((相同。由于转换规则 应用于二进制 + 运算符,如果 E1 是一个数组对象(等效地,指向 数组对象的初始元素(和 E2 是一个整数,E1[E2] 指定 E2-th 元素(从零开始计数(。

例如,你正在做的事情基本上是[]已经做的事情

另外(相同的标准(解释了为什么指针会像您注意到的那样递增:§6.5.6

在指针中添加或减去具有整数类型的表达式时,将 结果具有指针操作数的类型。如果指针操作数指向 一个数组对象,并且数组足够大,结果指向一个元素偏移量 原始元素使得结果和原始元素的下标的差异 数组元素等于整数表达式。换句话说,如果表达式 P 指向 数组对象的第 i 个元素,表达式 (P(+N(等效地为 N+(P((和 (P(-N(其中 N 的值为 n(分别指向 的 i+n 和 i−n 个元素 数组对象(如果它们存在(。此外,如果表达式 P 指向最后一个 元素,表达式 (P(+1 指向 数组对象,如果表达式 Q 指向数组对象的最后一个元素, 表达式 (Q(-1 指向数组对象的最后一个元素。如果两个指针 操作数和结果指向同一数组对象的元素,或者指向最后一个之后的元素 元素的数组对象,计算不得产生溢出;否则, 行为未定义。如果结果指向数组对象的最后一个元素,则 不得用作计算的一元 * 运算符的操作数。

编译器

知道ptr是指向 4 字节类型的指针,因此它知道ptr+1在内存中更远 4 个字节。

如果你想一想,很明显一定是这样,否则你就无法在不知道系统上(例如(整数的大小的情况下编写可移植代码。

此外,数组索引在幕后完全是指针算术 - 也就是说,array[3]*(array + 3)完全相同

为指针编制索引时,编译器知道索引应按单元格的大小前进,在本例中为 4 个字节的指针。

指针算术考虑指向类型的大小。例如,如果ptr的值是1234,因为ptrint*类型,那么p + 1的值是1234 + 1 * sizeof(int) == 1234 + 1 * 4 = 1238(假设sizeof(int) == 4(。

+ 运算符的右操作数(我们称之为 x(不是您移动指针的实际数量。因为 int 是 4 个字节,所以编译器知道实际跳到 x*4。

指针算术的单位是指向的对象,而不是字节。

如果p指向int对象,则p+1p+2p+3指向连续的int对象,而不是连续的字节。如果p指向一个大型结构,则它们指向该结构的连续实例。

编译器在后台完成其工作,将指针算术转换为机器地址算术。因此,它会根据需要乘以偏移量,以从对象单位转换为字节单位。

我的猜测是,根据你的说法,(ptr + 1)应该给你1235但显然没有。

除了其他人给出的关于为什么它加4并给你1238的答案之外,考虑一下它给你1235的情况,1235你没有整数元素(即数组的第二个元素(。但是你的指针应该指向一个整数。因此,它不会以这种方式工作。

指针算术是与普通算术不同的运算。在指针算术中,一个参数必须是指针类型,另一个参数必须是整数类型:

  1. intA + intB:正常算术,结果是总和。
  2. intA + pointerB:指针算术,执行的计算sizeof(*pointerB)*intA + pointerB
  3. pointerA + intB:指针算术,执行的计算pointerA + sizeof(*pointerA)*intB
  4. pointerA + pointerB : 非法

pointerA[intB]只是案例 2 ( pointerA + intB ( 的简写,这就是为什么它等同于 intB[pointerA](解析为案例 3(,但这仅在 IOCCC 中使用。