访问已分配内存中的变量

时间:2013-11-26 14:11:18

标签: c pointers

假设我想为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)

代替?它是如何工作的?

4 个答案:

答案 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)

你不应该。向指针添加int时发生的规则并不明显。所以最好不要使用你的直觉,而是阅读关于在这种情况下发生的事情的语言标准。例如,阅读有关指针算术here(C)或here(C ++)的更多信息。

很快 - 非空指针以类型长度为单位“测量”。