我可以使用不带alignof的指针算术在结构体中相同类型的连续字段序列之间移动吗?

问题描述 投票:0回答:1

知道还有其他类似的问题。我已阅读这些内容,但认为这个问题尚未得到解答。

我可以使用指针算术在连续的(在声明序列中连续的)相同类型结构的字段序列之间移动而不需要咨询

_Alignof
吗?

我可以在数组元素之间移动而无需咨询

_Alignof
,因为包含尾随填充。

但是,结构体中相同类型的连续字段是否可能与数组中的对齐方式不同?

换句话说,这段代码有可能是未定义的行为吗?

struct MyStruct {
    long int field_1;
    int field_2;
    int field_3;
};

int main(void) {
    struct MyStruct my_struct;
    int *field_2_ptr = &my_struct.field_2;
    int field_3_value = *(field_2_ptr + 1);
}

知道这是不好的做法。我意识到

->
。我知道填充通常会产生干扰。我想知道填充是否会干扰这种特定情况。

这个问题是关于C的。我不关心C++。

到目前为止,我已经使用 GCC 编译了它,并尝试使用 Valgrind 看看是否有问题,并使用 clang 和 UBSan 编译它。在这个系统(x86-64 Linux)上似乎没问题。

c pointers struct memory-alignment pointer-arithmetic
1个回答
0
投票

严格来说,这是未定义的行为。

允许在数组对象上进行指针算术(为此目的,单个对象被视为 1 元素数组),前提是原始指针和结果指针指向同一数组对象(或超出末尾的一个元素)。此外,指向尾后一位的指针不能被取消引用,否则会触发未定义的行为。

C 标准第 6.5.6p8 节中关于加法运算符对此进行了详细说明:

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

*
被评估的运算符。

粗体部分正是这里发生的情况:

int field_3_value = *(field_2_ptr + 1);

所以这会触发未定义的行为。

&my_struct.field_2 + 1 == &my_struct.field_3
的评估结果为 true 并不重要。

出于同样的原因,这也是未定义的行为:

int x[2][2] = {{1,2},{3,4}};
int y = x[0][2];
© www.soinside.com 2019 - 2024. All rights reserved.