这是我的结构:
struct Node {
struct Node* data;
struct Node* links[4];
}
假设没有填充,Node->links[-1]
是否确保指向Node::data
?
答案 0 :(得分:17)
不保证;这是未定义的行为:
在实践中,您最终可能会指向data
,但任何尝试访问它都会导致UB。
答案 1 :(得分:7)
数组下标是根据指针算法定义的,C99标准对指针算术有这个说法:
如果指针操作数和 结果指向的元素 相同的数组对象,或一个过去 数组对象的最后一个元素, 评估不得产生 溢流;否则,行为是 未定义。
因此,严格来说,访问Node->links[-1]
(即使只是获取Node->links[-1]
的地址)是未定义的行为。因此,您无法保证Node->links[-1]
能够获得Node::data
。
但正如许多评论家所提到的那样,它几乎总能奏效。我仍然认为应该避免的编程习惯很差。如果不是为了技术性,那么因为它要求对struct Node
的修改很容易导致编译器无法帮助你的错误。当有人在data
和links
之间添加内容时,事情就会神秘地破裂。
答案 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)
这是实现定义,取决于实现焊盘结构和数组的方式。但是,只要它以相同的方式填充结构和数组,它就应该可以工作。