在c ++中使用union时是否可以跳过字节? [英] Is it possible to skip bytes when using union, in c++?
问题描述
我正在尝试对两个结构使用联合,具体是将2D(4 x 4)浮点数组与4个Vector4对齐。
I'm attempting to use a union for a couple of structs, specfically aligning a 2D (4 by 4) float array with 4 Vector4's.
根据我的理解,union会从第一个字节开始查看顺序字节。如果我有一个4x4数组,并且想获得整列,则需要跳过16个字节才能到达下一行。
From my understanding, union looks at the sequential bytes from the first. If I have a 4x4 array and want to get a whole column, I would need to skip 16 bytes to get to the next row.
示例:
Matrix = {{a, b, c, d},
{e, f, g, h},
{h, i, j, k},
{l, m, n, o};
如果给出的数据使得一维数组为 {a,b ,c,d,e,...,o}
,我将如何获得最后一列(d,h,k,o)?
if the data is given such that a 1D array is {a,b,c,d,e,..., o}
, how would I get the last column (d,h,k,o)?
那么我将如何获取字节:12-> 16、28-> 32、44-> 48、60-> 64?
So how would I get the bytes: 12->16, 28->32, 44->48, 60->64?
我拥有的代码返回最后一行(不是我想要的)的是:
the code I have that returns the last row (not what I want), is:
//matrix.h
struct Matrix4 {
union{
float values[4][4];
Vector4 column[4];
};
//matrix methods etc
}
//main.cpp
Matrix4 position = Matrix3::translation(Vector3(1,2,3));
Vector4 column = position.column[2];
std::cout << (column) << std::endl;
输出矩阵将是(不记得如何使用LaTex格式):
The output matrix would be (don't remember how to use LaTex formatting sorry):
| 1 0 0 1 |
| 0 1 0 2 |
| 0 0 1 3 |
| 0 0 0 1 |
所以我想要的列是:
|1|
|2|
|3|
|1|
,工会给出:
|0|
|0|
|0|
|1|
(最后一行,而不是列)。
(the last row, not column).
将代码重构为使用一维数组来获取顺序字节会更容易,还是应该更改矩阵的构造方式?或者我可以用工会中的其他东西来处理这个问题?
Would it just be easier to refactor my code to use a 1D array to get the sequential bytes or should I change how my matricies are constructed? or can I handle this with some other thing in union?
编辑:我的问题与此其他问题,因为我已经创建了矩阵类并分配了内存。我的问题着眼于联合的功能及其局限性,以及使用我定义的结构 Vector4作为表示矩阵中某些数据的一种方式。我正在研究跳过字节以接收彼此不直接跟随的数据的可能性,而不是如何分配所述字节。
My question is different to this other question because I already have created a matrix class and allocated memory. My question looks at the functionality of "union" and its limits, as well as using my definied struct 'Vector4' as a means of representing some data in a matrix. I'm looking into the possibility of skipping bytes to receive data that doesn't directly follow each other, not how to allocate said bytes.
推荐答案
这是一种相当常见的模式,但无效。之所以受欢迎,是因为它很容易,而且因为传统上主流编译器已经允许并支持它。
This is a fairly common pattern, but an invalid one. It's popular because it's easy, and because mainstream compilers have traditionally permitted and supported it.
但是您根本无法以明确定义的方式在其中使用联合方式。并集不是将一种类型的数据重新解释为另一种类型的数据的一种方式。哎呀, reinterpret_cast
甚至都无法帮助您:为了安全地进行操作,您必须保留 std :: copy
来回移动您的字节。唯一安全的方法是使用 char []
(或 unsigned char []
或 std :: byte []
),可以为任意内存块添加别名:因此,联合对于快速字节检查很有用。除此之外,它们仅在您一次不需要使用多个工会会员的情况下才有用。
But you simply cannot, in a well-defined way, make use of unions in this manner. Unions are not a way to reinterpret data of one type as data of another type. Heck, reinterpret_cast
doesn't even get you there: to do it safely you'd have to keep std::copy
ing your bytes back and forth. The only time it's safe is with a char[]
(or unsigned char[]
, or std::byte[]
) which is allowed to alias arbitrary blocks of memory: as a consequence, unions can be useful for quick byte inspection. Beyond that, they are useful only if you don't need to use more than one of the union's members at a time.
您真正应该做的是选择一个布局/格式,然后在顶部添加您自己的 operator []
(或其他功能)变体,以提供不同的接口和解释数据的方式您的呼叫站点。
What you should really be doing is picking one layout/format, then adding your own operator[]
(or other function) variants on top to provide different interfaces and ways of interpreting the data at your call site.
做正确,不会有任何开销。
Do it right and there'll not be any overhead.
巧妙地做您将能够按照需要的方式即时应用转换。提供一种代理类型,一种迭代器,它不仅可以按线性顺序进行迭代,还可以按所需的修改顺序进行迭代。
Do it cleverly and you'll be able to apply your transformation "on the fly" in just the way you need. Provide a proxy type, a kind of iterator, that doesn't just iterate in linear sequence but instead iterates in the modified sequence that you need.
封装在您的 Matrix4
类型中。
这篇关于在c ++中使用union时是否可以跳过字节?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!