上下文:为了提高速度,我决定将用 Python 开发的 3D 图形脚本改写为 C 语言。这涉及到我学习 C。有问题的程序部分缓存有关 3D 网格的法线信息。
这里按顺序调用了 3 个 vector 运算(非常标准: vector 减法以获得边 vector 、叉积和平均值),我希望尽可能快,所以我尽量避免存储任何不必要的东西在堆上......并多次复制我的结构。但是,我也知道,如果我返回指针,我将指向不再有效的内存空间。
这就是我尝试编写所有三个函数的方式(一般来说:结构复制,结构复制,而不是指针)。
typedef struct vector vector;
struct vector{
double x,y,z;
};
vector vect(vector a, vector b){
vector res;
res.x = b.x - a.x;
res.y = b.y - a.y;
res.z = b.z - a.z;
return res;
}
vector cross(vector a, vector b){
vector res;
res.x = a.y*b.z - a.z*b.y;
res.y = a.z*b.x - a.x*b.z;
res.z = a.x*b.y - a.y*b.x;
return res;
}
vector avg (vector a, vector b){
vector res;
res.x = (a.x + b.x)/2;
res.y = (a.y + b.y)/2;
res.z = (a.z + b.z)/2;
return res;
}
这就是它的名字:
m->Tpolynormals[i] = avg(cross( vect(*p->verts[0], *p->verts[1]),
vect(*p->verts[1], *p->verts[2]) ),
cross( vect(*p->verts[2], *p->verts[3]),
vect(*p->verts[3], *p->verts[0]) )
);
这是相当有效还是有更快的方法?我知道我可以尝试并“让它发挥作用”,但在这一点上我想确保基础牢固。 - 谢谢
编辑:在上面添加了我的结构定义,正如有人明显指出的那样,呃。坐标是 double 的(这是我的 3D 包输出的),系统是 64 位的。
最佳答案
“避免(初学者的)分配错误”与“我想尽可能快”
哪个更重要?
如果代码需要尽可能快,请尝试多种方法并分析它们,看看哪种方法最适合您。你会犯错误。
vector
的大小处于边界区域,提供最佳答案的一般答案,按值或其地址传递 vector
。最好两者都试一下
1) 按值传递vector
。 OP 似乎很了解这一点。
vector vect(vector a, vector b){
vector res;
res.x = b.x - a.x;
res.y = b.y - a.y;
res.z = b.z - a.z;
return res;
}
2) 通过地址传递vector
。创建中间结果位置。这似乎是OP不确定的部分。
void V_vect(vector *res, const vector *a, const vector *b){
res->x = b->x - a->x;
res->y = b->y - a->y;
res->z = b->z - a->z;
}
// usage example
vector res1;
vector res2;
V_vect(&res1, p->verts[0], p->verts[1]);
V_vect(&res2, p->verts[1], p->verts[2]);
vector res3;
V_cross(&res3, &res1, &res2);
V_vect(&res1, p->verts[2], p->verts[3]);
V_vect(&res2, p->verts[3], p->verts[0]);
vector res4;
V_cross(&res4, &res1, &res2);
V_avg(&m->Tpolynormals[i], &res3, &res4);
特别是,建议避免在下面的同一调用中重复使用内存。这可能是新手犯的错误,无论是在功能上还是在代码性能上。
V_cross(&res2, &res1, &res2);
在传递地址时加快速度的一种方法是使用restrict
。这允许编译器知道调用代码正在使用指向不重叠区域的指针。这允许进行某些编译器优化。
void V_vect(vector * restrict res, const vector * restrict a, const vector * restrict b){
res->x = b->x - a->x;
res->y = b->y - a->y;
res->z = b->z - a->z;
}
使用 restrict
时,下面的第一个调用是未定义的行为,因为它与 vector
重叠。
// V_cross(&res2, &res1, &res2); // bad
V_cross(&res4, &res1, &res2); // good
尝试各种方法(包括 @Jonathan Leffler compound literal idea 和 @Jonathan Leffler inline idea )并使用适合您的方法。
关于c - 在 C 中的 vector 函数序列中避免(初学者)分配错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38129062/