假设我想为3个整数分配内存:
int *pn = malloc(3 * sizeof(*pn));
现在为我们分配值:
pn[0] = 5550;
pn[1] = 11;
pn[2] = 70000;
要访问第二个值,我会这样做:
pn[1]
但[n]运算符只是*(a + n)的快捷方式。那么这意味着我在索引后访问第一个字节。但int是4个字节长,所以我不知道
*(a+sizeof(*a)*n)
代替?它是如何工作的?
答案 0 :(得分:12)
不,编译器会处理这个问题。指针算法中有一些特殊的规则,就是其中之一。
如果您真的只想将其递增一个字节,则必须将指针强制转换为指向一个字节长的类型的指针(例如char
)。
答案 1 :(得分:8)
很好的问题,但C会自动将偏移量乘以指向类型的大小。换句话说,当您访问
时p[n]
表示声明为
的指针T *p;
您将隐式访问地址p + (sizeof(T) * n)
。
答案 2 :(得分:1)
例如,我们可以使用C99标准来查明发生了什么。根据C99标准:
6.5.2.1数组下标
约束
- 1 其中一个表达式应具有类型''指向对象类型的指针'',另一个表达式应该 具有整数类型,结果类型为''type'' 语义
- 2后缀表达式后跟方括号 [] 中的表达式是下标 指定数组对象的元素。下标运算符 [] 的定义 是 E1 [E2] 与(*((E1)+(E2)))相同。由于转换规则 应用于二进制+运算符,如果 E1 是一个数组对象(等效地,指向 数组对象的初始元素)和 E2 是整数, E1 [E2] 表示 E2-th 元素 E1 (从零开始计算)。
关于+
运算符的转换规则,从6.5.5.8开始:
当指针中添加或减去具有整数类型的表达式时, result具有指针操作数的类型。如果指针操作数指向的元素 一个数组对象,并且该数组足够大,结果指向一个偏移的元素 原始元素使得结果和原始的下标不同 数组元素等于整数表达式。换句话说,如果表达式P指向 数组对象的第i个元素,表达式(P)+ N(等效地,N +(P))和 (P)-N(其中N具有值n)分别指向第i + n和第i-n个元素 数组对象,只要它们存在。而且,如果表达式P指向最后一个 数组对象的元素,表达式(P)+1指向一个过去的最后一个元素 数组对象,如果表达式Q指向一个数组对象的最后一个元素, 表达式(Q)-1指向数组对象的最后一个元素。如果两个指针 操作数和结果指向同一个数组对象的元素,或者指向最后一个数组对象的元素 数组对象的元素,评估不得产生溢出;否则, 行为未定义。如果结果指向一个超过数组对象的最后一个元素的那个,那么 不得用作被评估的一元*运算符的操作数。
因此,所有这些注释都是关于你的情况,它的工作原理和你写的一样,你不需要特殊的构造,解除引用或其他任何东西(指针算术为你做这些):
pn[1] => *((pn)+(1))
或者,就字节指针而言(为了简化描述的内容),此操作类似于:
pn[1] => *(((char*)pn) + (1*sizeof(*pn)))
此外,您可以使用1[pn]
访问此元素,结果将相同。
答案 3 :(得分:0)