将数组作为结构访问与未定义的行为
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++ 中使用它们作为编译器扩展。然而,结构和数组的别名是不允许的。以上是关于将数组作为结构访问与未定义的行为的主要内容,如果未能解决你的问题,请参考以下文章