【问题标题】:Accessing variables in allocated memory访问分配内存中的变量
【发布时间】:2013-11-26 14:11:17
【问题描述】:

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

相反?它是如何工作的?

【问题讨论】:

  • 绝对没有说*(a + n) 以字节为单位工作;除非a 当然是一个字节指针。所有的指针算术都是根据指​​针的类型来计算的。

标签: c pointers


【解决方案1】:

不,编译器会处理这个问题。指针运算有一些特殊的规则,这就是其中之一。

如果你真的只想增加一个字节,你必须将指针转换为一个指向一个字节长的类型的指针(例如char)。

【讨论】:

  • 是否每个 C 编译器都必须这样做(是否严格、标准化)?
  • 是的。至少 C 语言定义为一个字节。
  • 那么 *(n + 1) 呢?它是访问第二个字节还是与 n[1] 相同?
  • 它的工作原理与n[1] 相同。正如您在帖子中所指出的,[] 在这种情况下只是一些捷径。
【解决方案2】:

好问题,但是 C 会自动将偏移量乘以所指向类型的大小。换句话说,当你访问

p[n]

对于声明为的指针

T *p;

您将隐式访问地址p + (sizeof(T) * n)

【讨论】:

    【解决方案3】:

    例如,我们可以使用 C99 标准来找出发生了什么。根据C99标准:

    6.5.2.1 数组下标
    约束
    - 1 其中一个表达式应具有类型“指向对象类型的指针”,另一个表达式应 具有整数类型,结果具有“类型”类型。
    语义
    - 2 后缀表达式后跟方括号 [] 中的表达式是下标 指定数组对象的元素。下标运算符[]的定义 是 E1[E2] 等同于 (*((E1)+(E2)))。由于转换规则 适用于二元 + 运算符,如果 E1 是一个数组对象(等效地,指向 数组对象的初始元素)并且E2是一个整数,E1[E2]表示E2-th E1 的元素(从零开始计数)。

    从 6.5.5.8 开始,关于 + 运算符的转换规则:

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

    因此,所有这些注释都是关于你的案例,它完全按照你写的那样工作,你不需要特殊的构造、取消引用或其他任何东西(指针算术为你做这些):

    pn[1] => *((pn)+(1))
    

    或者,就字节指针而言(为了简化描述发生了什么),此操作类似于:

    pn[1] => *(((char*)pn) + (1*sizeof(*pn)))
    

    此外,您可以使用1[pn] 访问此元素,结果将是相同的。

    【讨论】:

      【解决方案4】:

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

      简而言之 - 非空指针以类型长度为单位“测量”。

      【讨论】:

      • 我会小心那个页面,它说的是 C,但大部分代码是 C++。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-05
      • 1970-01-01
      • 2015-03-08
      相关资源
      最近更新 更多