C++ 静态数组缓冲区分配
假设我定义了一个数组C++ 静态数组缓冲区分配,c++,arrays,buffer,C++,Arrays,Buffer,假设我定义了一个数组float floatBuffer[4],我有一个结构:struct vec3{float x,y,z;}myVec 在vec3赋值之前,我赋值:floatBuffer[3]=0.0f (如果可能的话,)我可以通过什么方式将myVec分配给floatBuffer[0](二进制副本),以便 floatBuffer[0]==myVec.x floatBuffer[1]==myVec.y floatBuffer[2]==myVec.z 浮动缓冲区[3]==0.0f ? 显
float floatBuffer[4]
,我有一个结构:struct vec3{float x,y,z;}myVec代码>
在vec3赋值之前,我赋值:floatBuffer[3]=0.0f代码>
(如果可能的话,)我可以通过什么方式将myVec
分配给floatBuffer[0]
(二进制副本),以便
- floatBuffer[0]==myVec.x
- floatBuffer[1]==myVec.y
- floatBuffer[2]==myVec.z
- 浮动缓冲区[3]==0.0f
?
显而易见的答案是:
floatBuffer[0] = myVec.x;
floatBuffer[1] = myVec.y;
floatBuffer[2] = myVec.z;
如果您愿意对结构布局进行假设,并且编译器为直接赋值生成了蹩脚的代码,请记录您的假设并执行memcpy
:
static_assert(sizeof(myVec) == sizeof(float[3]), "myVec should not have padding");
memcpy(&floatBuffer[0], &myVec, sizeof(myVec));
该标准确实指出,即使在标准布局结构中(但不是在开头),也可能存在填充,因此二进制副本可能不可移植。但是,给定特定的系统和包装说明(查找#pragma pack
),您可能只能使用memcpy
您可以尝试以下操作:
#include <cstring>
#include <algorithm>
#include <iterator>
#include <iostream>
// look up your compiler's documentation
//#pragma pack(4)
struct fs {
float x, y, z;
};
int main() {
fs b = {1.0, 2.0, 3.0};
float p[ 4 ] = {0};
static_assert( sizeof b == sizeof p - 1, "warning: padding detected!" );
std::memcpy(&p[ 0 ], &b, sizeof p - 1);
std::copy(&p[ 0 ], &p[ 0 ] + 3, std::ostream_iterator<float>(std::cout, "\n"));
}
#包括
#包括
#包括
#包括
//查找编译器的文档
//#布拉格语包(4)
结构fs{
浮动x,y,z;
};
int main(){
fs b={1.0,2.0,3.0};
浮点p[4]={0};
静态_断言(sizeof b==sizeof p-1,“警告:检测到填充!”);
标准::memcpy(&p[0],&b,p-1的大小);
std::copy(&p[0],&p[0]+3,std::ostream_迭代器(std::cout,“\n”);
}
可以使用memcpy,但是如上所述,memcpy可能会因包装不同而易碎
我认为这里最好的解决方案是使用多个语句,而不是过于复杂
floatBuffer[0] = myVec.x;
floatBuffer[1] = myVec.y;
floatBuffer[2] = myVec.z;
用显而易见的方式来做。。。
代码很清楚正在发生什么,您可以让编译器为您优化代码
我确实想到了一个问题,
这就是为什么要使用浮点数组而不是vec3或vec3数组(这将允许一次赋值)您可以为此编写一个函数
struct vec3{float x,y,z;} myVec;
float* operator<< (float t[4], vec3 v) {
t[0] = v.x; t[1] = v.y; t[2] = v.z; t[3] = 0;
return t;
}
int main() {
float test[4];
test << myVec; // now do the assignment 'in one go'
return 0;
}
structvec3{float x,y,z;}myVec;
float*操作符,如果他控制了声明,他可以执行float floatBuffer[4]={myVec.x,myVec.y,myVec.z}
@xcrypt如果你把它放在一个函数中,然后调用那个函数,它算“一次性”吗?(对我来说)这只是字面上的复制数据。这两者之间没有区别,只是使用您建议的指针需要编译器以某种方式布置结构。@xcrypt哦,对了,我忘了。它不能“仅仅选取所有字节并复制它们”,因为计算机并不神奇。也就是说,这并不意味着生成的程序集将有一个循环。我怀疑赋值和memcpy会产生非常相似的生成代码。@xcrypt哦,它们可以一次复制“多个字节”,但数量有限。因为最终,下面的硬件对一次可以传输的字节数有限制。总线没有无限的带宽。由于floatbuffer
是静态的(我从标题中假设这一点),所有数组元素都将初始化为零,除非您为它们提供其他非零编译时常量。当然,您以后可以修改它们。指定初始值有问题吗?因为我希望floatbuffer能够表示任何内容。例如,在DirectX顶点缓冲区中表示顶点,您可能会考虑要使用的类型的联合。