Lig*_*rms 6 c void-pointers octree
我目前在C中使用自己的八叉树.树将包含几十亿个对象,因此内存效率是关键.为了实现这一点,我目前使用一个带有标志和联合的结构,但我认为它不干净并且它浪费了内部节点的空间,因为我只需要一个8位标志但是为64位保留了内存指数.我的代码目前如下:
typedef struct _OctreeNode
{
uint64_t location_code;
union
{
uint8_t child_exists;
uint64_t object_index;
} data;
uint8_t type;
} OctreeNode;
Run Code Online (Sandbox Code Playgroud)
我想把它分成两个不同的结构.一个叶节点和一个内节点.如下:
typedef struct _OctreeInnerNode
{
uint64_t location_code;
uint8_t child_exists;
uint8_t type;
} OctreeInnerNode;
typedef struct _OctreeLeafNode
{
uint64_t location_code;
uint64_t object_index;
uint8_t type;
} OctreeLeafNode;
Run Code Online (Sandbox Code Playgroud)
现在问题出现在我的无序地图上,基于位置代码的哈希值.它使用void指针,因此存储两个不同的结构不是问题.我知道有可能将标志作为第一个元素并取消引用指向flag数据类型的指针来派生类型,如下所示:
typedef struct _OctreeLeafNode
{
uint8_t type;
uint64_t location_code;
uint64_t object_index;
} OctreeLeafNode;
void
func(void* node)
{
uint8_t type = *(uint8_t*)node;
if (type == LEAF_NODE) {
OctreeLeafNode* leaf_node = (OctreeLeafNode*)node;
}
}
Run Code Online (Sandbox Code Playgroud)
我想知道是否有更清洁的方式.或者这不推荐?我怎么能处理结构和void指针的多种可能性?
提前致谢!
这是一种常用的方法C.
但是只需将这些字段放在结构的开头(第一个字段)并且永远不要改变它们的位置.此外,您需要将它们保留在所有结构中.
此方法的常见示例是version结构中的字段(或type在您的情况下).您可以将它们保留在结构的开头,然后通过类似的方法检查结构版本.这样的事情:
struct _base {
uint8_t ver;
};
#define TYPE_OLD 0
struct _a_old {
struct _base info;
uint8_t a;
};
#define TYPE_NEW 1
struct _a_new {
struct _base info;
uint8_t a;
uint8_t b;
};
Run Code Online (Sandbox Code Playgroud)
现在,您可以通过将数据转换为struct _base检查ver字段来识别不同类型.
unsigned char* buf = ...
switch (((struct _base*)buf)->ver)
{
case TYPE_OLD:
{
struct _a_old* old = (struct _a_old*)buf;
// ...
break;
}
case TYPE_NEW:
{
struct _a_new* old = (struct _a_new*)buf;
// ...
break;
}
default:
// ...
}
Run Code Online (Sandbox Code Playgroud)