将数组作为结构访问与未定义行为
Accessing an array as a struct vs undefined behavior
假设我们有一个包含 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
是的,这确实是一个未定义的行为。它违反了所谓的严格别名规则——禁止通过 unrelated 指针访问对象(我不会详细说明什么是 unrelated在这里,除非特别要求)。
但是,浮点数组与结构无关。
这是标准 (3.10 / 10) 的摘录:
If a program attempts to access the stored value of an object through
a glvalue of other than one of the following types the behavior is
undefined:
— the dynamic type of the object,
— a cv-qualified version of the dynamic type of the object,
— a type similar (as
defined in 4.4) to the dynamic type of the object,
— a type that is
the signed or unsigned type corresponding to the dynamic type of the
object,
— a type that is the signed or unsigned type corresponding to
a cv-qualified version of the dynamic type of the object,
— an aggregate or union type that includes one of the aforementioned types
among its elements or nonstatic data members (including, recursively,
an element or non-static data member of a subaggregate or contained
union),
— a type that is a (possibly cv-qualified) base class type of
the dynamic type of the object,
— a char or unsigned char type.
假设我们有一个包含 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
是的,这确实是一个未定义的行为。它违反了所谓的严格别名规则——禁止通过 unrelated 指针访问对象(我不会详细说明什么是 unrelated在这里,除非特别要求)。
但是,浮点数组与结构无关。
这是标准 (3.10 / 10) 的摘录:
If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined:
— the dynamic type of the object,
— a cv-qualified version of the dynamic type of the object,
— a type similar (as defined in 4.4) to the dynamic type of the object,
— a type that is the signed or unsigned type corresponding to the dynamic type of the object,
— a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object,
— an aggregate or union type that includes one of the aforementioned types among its elements or nonstatic data members (including, recursively, an element or non-static data member of a subaggregate or contained union),
— a type that is a (possibly cv-qualified) base class type of the dynamic type of the object,
— a char or unsigned char type.