如果我们从AoS布局开始,AoS结构可以很容易地初始化为:
struct Position { float x; float y; };
struct Position positions[] = {
{ .x = 1.f, .y = 2.f },
{ .x = 20.f, .y = 30.f },
{ .x = 150.f, .y = 200.f },
{ .x = 1000.f, .y = 2000.f },
};
字符串
数据总是按照我想要的方式分组,每个AoS结构中有两个值。在内存中,它看起来像:
| 1.f 2.f | 20.f 30.f | 150.f 200.f | 1000.f 2000.f |
型
如果我将其交换为SoA布局,SoA数据可以像这样轻松地初始化:
float position_x[] = { 1.f, 20.f, 150.f, 1000.f },
float position_y[] = { 2.f, 30.f, 200.f, 2000.f };
型
这些数据总是按照我希望的方式分组,每个SoA数组中有一个值。在内存中,它看起来像:
| 1.f 20.f 150.f 1000.f |
| 2.f 30.f 200.f 2000.f |
型
当涉及到AoSoA布局时,如果宽度是固定的,它就可以工作,这里是[2]
:
struct Position { float x[2]; float y[2]; };
struct Position positions[] = {
{ .x = { 1.f, 20.f },
.y = { 2.f, 3.f } },
{ .x = { 150.f, 1000.f },
.y = { 200.f, 2000.f } },
};
型
这里的分组是每个AoSoA结构中的2对[2]
,每个值为2(x,y
)。在内存中,它看起来像:
| 1.f 20.f | 150.f 1000.f |
| 2.f 30.f | 200.f 1000.f |
型
但是如果我想将宽度更改为[4]
,前面的代码会让AoSoA结构体有一半是“空的”。AoSoA宽度[4]
意味着要用作4对[4]
的2个值(x,y
),但前面的代码仍然只会在每个AoSoA结构体的下部给予我2对2个值,让子数组的上部槽为空(初始化为零)。就像这样:
| 1.f 20.f ZERO ZERO | 150.f 1000.f ZERO ZERO |
| 2.f 30.f ZERO ZERO | 200.f 1000.f ZERO ZERO |
型
如果我想让我的数据保持分组状态,使得子数组的所有[4]
空间都被我的数据填充,我必须像这样重写初始化器:
struct Position { float x[4]; float y[4]; };
struct Position positions[] = {
{ .x = { 1.f, 20.f, 150.f, 1000.f },
.y = { 2.f, 3.0f, 200.f, 2000.f } },
};
型
在内存中,它看起来像这样:
| 1.f 20.f 150.f 1000.f |
| 2.f 30.f 200.f 1000.f |
型
如果我改变我的AoSoA的宽度,零开始出现在数据中,但我不想零。无论AoSoA的宽度是多少,我都希望数据保持紧密分组。我正在寻找一种方法来编写我的初始化器,这样数据将自动保持分组。
有没有一种方法可以让我为我的AoSoA数据创建一个初始化列表,这样我就可以改变AoSoA的宽度并获得所需的行为?
1条答案
按热度按时间afdcj2ne1#
C语言中的部分初始化器的规则是,所有剩余的对象都被初始化,就像被赋值为0、0.0或NULL一样(取决于类型,并且是递归的)。因此,如果你声明的数组大于你提供的初始化器的数量,你总是会得到其余的赋值为0。
您可以使用动态内存分配(例如malloc)如果你在编译时不知道你的数组有多大。