代码之家  ›  专栏  ›  技术社区  ›  uray

C负数组索引

  •  10
  • uray  · 技术社区  · 15 年前

    这是我的结构:

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

    假设没有填充,是吗 Node->links[-1] 一定会指向 Node::data ?

    7 回复  |  直到 15 年前
        1
  •  17
  •   Oliver Charlesworth    15 年前

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

    • 依赖于编译器的结构填充
    • 可能的严格别名冲突

    data ,但任何访问它的尝试都将导致UB。

        2
  •  7
  •   Michael Burr    15 年前

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

    如果指针操作数和 相同的数组对象,或一个过去的 评估不得产生 未定义。

    所以访问 Node->links[-1] 节点->链接[-1] 节点->链接[-1] Node::data .

    struct Node 很容易导致编译器无法帮助您解决的错误。当有人在 data links ,事情会神秘地破裂。

        3
  •  3
  •   Keith Randall    15 年前

    一个 union 可能对你有帮助。像这样的:

    struct Node {
      union {
        Node *data;
        struct {
          Node *lnk[5];
        } links;
      }
    }
    
        4
  •  2
  •   ruslik    15 年前

    我想说是的,但为什么不声明

    struct Node {
        struct Node* links[5];
    }
    
        5
  •  0
  •   DigitalRoss    15 年前

    几乎 是的

    指向 data ,但这可能并不完全是一种保证。

    x[-1] 是同一件事 *(x - 1) ,所以,取决于你在 x - 1 ,那么你确实有某种担保。(不要忘记,当从指针中减去时,减量是按项的大小计算的。)

    尽管其他人反对的理由是 严格混叠 ,在这种情况下,类型是相同的,因此详细的优化不应删除预期的行为。

        6
  •  -2
  •   Eugene Smith    15 年前

    我想是的。但标准并不能保证没有填充物。

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

        7
  •  -2
  •   Chris Dodd    15 年前

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