将数组作为结构访问与未定义的行为

Posted

技术标签:

【中文标题】将数组作为结构访问与未定义的行为【英文标题】:Accessing an array as a struct vs undefined behavior 【发布时间】:2016-05-13 13:27:35 【问题描述】:

假设我们有一个包含 4 个 float 值的结构和一个包含 4 个元素的 float 数组。

然后是否将数组作为Foo 实例访问并通过该实例更改数组元素是未定义的行为?

struct Foo

    float a;
    float b;
    float c;
    float d;
;

float values[4] =  1.0f, 1.0f, 1.0f, 1.0f ;

int main()

    auto& floats = *reinterpret_cast<Foo*>(values);
    floats.a = 0.0f;
    floats.b = 0.0f;
    floats.c = 0.0f;
    floats.d = 0.0f;

在线编译运行:http://cpp.sh/6y7m

【问题讨论】:

调用严格别名,严格别名,我们在第7行调用。 这怎么可能定义得很好?每个班级成员之间可能存在任意填充。 @LightnessRacesinOrbit 对。想要黑白的:) 事实上,@LightnessRacesinOrbit 是在说别的。比方说,你用字符数组替换你的浮点数组,并开始在某个偏移量处访问它的元素并将浮点值复制到其中。该程序将是格式良好的,并且不会有未定义的行为。但是由于填充,您不太可能在结构中找到包含您期望它们的值的浮点成员。 【参考方案1】:

是的,这确实是一种未定义的行为。它违反了所谓的严格别名规则 - 禁止通过 unrelated 指针访问对象(我不会在这里详细说明 unrelated 什么,除非特别要求) .

但是,浮点数数组与结构无关。

这是标准 (3.10 / 10) 的摘录:

如果程序尝试通过以下方式访问对象的存储值 行为是以下类型之一以外的泛左值 未定义:

——对象的动态类型,

——对象动态类型的 cv 限定版本,

——一个类似的类型(如 4.4) 中定义的对象的动态类型,

——一个类型是 对应于动态类型的有符号或无符号类型 对象,

— 有符号或无符号类型,对应于 对象的动态类型的 cv 限定版本,

— 包含上述类型之一的聚合或联合类型 在其元素或非静态数据成员之间(包括递归地, 子聚合或包含的元素或非静态数据成员 联合),

— 一种类型,它是(可能是 cv 限定的)基类类型 对象的动态类型,

— char 或 unsigned char 类型。

【讨论】:

您能详细说明一下吗?或者也许将我指向标准中的相关部分?谢谢! @JohannGerell,我最喜欢的部分 :) 给我 3 分钟。 感谢您对“无关”的详细阐述 - 我也有这种预感。 @JohannGerell en.cppreference.com/w/cpp/language/… @JohannGerell C 语言有different rules,它比 C++ 更宽松,许多编译器允许在 C++ 中使用它们作为编译器扩展。然而,结构和数组的别名是不允许的。

以上是关于将数组作为结构访问与未定义的行为的主要内容,如果未能解决你的问题,请参考以下文章

是否在临时变量未定义行为中访问数组?

检查对象属性时与未定义或“未定义”的比较。有什么不同?

javascript 空与未定义

javascript 空与未定义

redis配置文件与未授权访问

是否将地图尺寸作为值插入地图未定义的行为?