ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

c-将结构转换为数组

2019-10-12 11:10:12  阅读:388  来源: 互联网

标签:reinterpret-cast c arrays struct alias


这个问题已经在这里有了答案:            >            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 address A, a pointer of type cv T* whose value is the
address A 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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有