C负数组索引

时间:2010-10-24 00:46:29

标签: c++ c arrays indexing

这是我的结构:

struct Node {
    struct Node* data;
    struct Node* links[4];
}

假设没有填充,Node->links[-1]是否确保指向Node::data

7 个答案:

答案 0 :(得分:17)

不保证;这是未定义的行为:

  • 依赖于编译器的结构填充
  • 标准仅定义0和长度(包括)之间的数组索引
  • 可能的严格别名违规

在实践中,您最终可能会指向data,但任何尝试访问它都会导致UB。

答案 1 :(得分:7)

数组下标是根据指针算法定义的,C99标准对指针算术有这个说法:

  

如果指针操作数和   结果指向的元素   相同的数组对象,或一个过去   数组对象的最后一个元素,   评估不得产生   溢流;否则,行为是   未定义。

因此,严格来说,访问Node->links[-1](即使只是获取Node->links[-1]的地址)是未定义的行为。因此,您无法保证Node->links[-1]能够获得Node::data

但正如许多评论家所提到的那样,它几乎总能奏效。我仍然认为应该避免的编程习惯很差。如果不是为了技术性,那么因为它要求对struct Node的修改很容易导致编译器无法帮助你的错误。当有人在datalinks之间添加内容时,事情就会神秘地破裂。

答案 2 :(得分:3)

union可能会对您有所帮助。像这样:

struct Node {
  union {
    Node *data;
    struct {
      Node *lnk[5];
    } links;
  }
}

答案 3 :(得分:2)

我会说是,但为什么不将其声明为

struct Node {
    struct Node* links[5];
}

答案 4 :(得分:0)

几乎

是的,几乎可以肯定指向data,但这可能不是一个保证。

你确实得到x[-1]*(x - 1)相同的保证,所以,根据你在x - 1的地址放置的内容,那么你确实有一种保证。 (并且不要忘记,当从指针中减去时,减量取决于项目的大小。)

虽然其他人在严格别名的基础上提出异议,但在这种情况下,类型是相同的,因此精心优化不应删除您预期的行为。

答案 5 :(得分:-2)

我认为是。但是标准没有保证没有填充。

编辑:但是标准还说如果“数组下标超出范围,行为是未定义的,即使某个对象显然可以使用给定的下标访问”。

答案 6 :(得分:-2)

这是实现定义,取决于实现焊盘结构和数组的方式。但是,只要它以相同的方式填充结构和数组,它就应该可以工作。