c-将结构转换为数组
作者:互联网
这个问题已经在这里有了答案: > Does accessing the first field of a struct via a C cast violate strict aliasing? 1个
> Reinterpret struct with members of the same type as an array in a standard compliant way 5个
这是一个严格的别名问题,因为编译器会因此引起任何优化顺序问题.
假设我在结构XMFLOAT3中具有三个公共浮点数(与this one不同).我想转换为浮点数*.这会使我陷入优化麻烦吗?
XMFLOAT3 foo = {1.0f, 2.0f, 3.0f};
auto bar = &foo.x;
bar[2] += 5.0f;
foo.z += 5.0f;
cout << foo.z;
我认为这将始终打印“ 13”.但是这段代码呢:
XMFLOAT3 foo = {1.0f, 2.0f, 3.0f};
auto bar = reinterpret_cast<float*>(&foo);
bar[2] += 5.0f;
foo.z += 5.0f;
cout << foo.z;
我相信这是合法的,因为根据http://en.cppreference.com/w/cpp/language/reinterpret_cast#Type_aliasing
T2 is an aggregate type or a union type which holds one of the aforementioned types as an element or non-static member (including, recursively, elements of subaggregates and non-static data members of the contained unions): this makes it safe to cast from the first member of a struct and from an element of a union to the struct/union that contains it.
我对此的理解正确吗?
显然,这将成为依赖XMFLOAT3声明的实现.
解决方法:
从XMFLOAT3 *到float *的reinterpret_cast正常,原因是:
9.2 [class.mem]第20段:
If a standard-layout class object has any non-static data members, its address is the same as the address of its first non-static data member. Otherwise, its address is the same as the address of its first base class
subobject (if any). [ Note: There might therefore be unnamed padding within a standard-layout struct object, but not at its beginning, as necessary to achieve appropriate alignment. — end note ]
这意味着第一个成员的地址是该结构的地址,并且在访问* bar时不涉及别名,因为您是通过float类型的左值访问float的,这很好.
但是强制转换也是不必要的,它等效于第一个版本:
auto bar = &foo.x;
如果结构的成员之间没有填充,或者更确切地说,如果数据成员的布局与数组float [3]相同,则表达式bar [2]是正确的,在这种情况下为3.9.2 [ basic.compound]第3段说还可以:
A valid value of an object pointer type represents either the address of a byte in memory (1.7) or a null pointer (4.10). If an object of type
T
is located at an addressA
, a pointer of type cvT*
whose value is the
addressA
is said to point to that object, regardless of how the value was obtained.
在实践中,没有理由不会将三个相同类型的相邻非静态数据成员与一个数组完全相同地放置(并且我认为Itanium ABI可以保证),但是为了安全起见,您可以添加:
static_assert(sizeof(XMFLOAT3)==sizeof(float[3]),
"XMFLOAT3 layout must be compatible with float[3]");
或偏执狂,或者z后面只有其他成员:
static_assert(offsetof(XMFLOAT3, y)==sizeof(float)
&& offsetof(XMFLOAT3, z)==sizeof(float)*2,
"XMFLOAT3 layout must be compatible with float[3]");
Obviously this will become implementation dependent on the declaration of XMFLOAT3.
是的,它依赖于它是标准布局类类型,并且依赖于它的数据成员的顺序和类型.
标签:reinterpret-cast,c,arrays,struct,alias 来源: https://codeday.me/bug/20191012/1899798.html