我正在设计一个经典的虚拟机,该虚拟机将在某种通用的,类型转换的值上运行-现在用标记的联合表示:
typedef struct val {
val_type type;
union {
int i;
unsigned int u;
double f;
str * str;
vec * vec;
map * map;
};
} val;
我在网上找到了大量有关此问题的文献,并得出结论认为这是解决问题的一种非常传统的方法。我想知道,是否可以通过以下方法来提高性能:
typedef struct val_int {
val_type type;
int i;
};
typedef struct val_str {
val_type type;
char * buffer;
size_t length;
size_t capacity;
};
typedef struct val_vec {
val_type type;
val_type ** members; // <-- access member by cast
size_t length;
size_t capacity;
};
在这里,我的理由是,在访问类似于原始类型的额外间接访问的成本(以及需要执行单独的分配-可能是通过池的帮助)之间存在权衡,而这种开销与诸如val_vec
,将其代表的当前胖指针的大小减半。我知道这里的简单答案是“对其进行度量”,但是我很难提出一个具有代表性的模型,而该模型本身并不是完整的实现。
第二种方法是否有名称,并且-假设将对其进行仔细管理(但不假设它不会引起未定义的行为),则存在被人们广泛理解的风险:米不占?这里首选哪种方法?
顺便说一句,是否也可以类似地使用灵活数组成员?
答案 0 :(得分:0)
我想在访问原始类型的额外间接成本之间要进行权衡
Premature optimization很少值得您花费宝贵的编码时间。这里的任何变化最多都是线性的。 6.001和其他1/2打。
在您选择的情况下,一种或另一种方法可能更好,但是提供给编译器的信息越多,优化的可能性就越大。
为清楚起见,通常避免使用强制转换的代码。
该替代方案缺少细节,并且在通常的不正确假设下可能会出现问题:void *
或val_type *
是通用指针,指向FP的指针可以很好地转换为其他指针,对齐方式强制转换对于其他类型而言已足够,而无需使用抗锯齿。
答案 1 :(得分:0)
在后一种情况下,您可能还会定义
typedef union val {
val_type type;
struct val_int val_int;
struct val_str val_str;
struct val_vec val_vec;
} val;
,现在您拥有一个可以容纳任何值类型的联合类型。确实,这是在匿名联合和结构存在之前执行此操作的常用方法。当您拥有一个只知道将成为val_int的对象时,只需分配val_int并将其地址转换为val *
,就可以节省几个字节的内存。