演员能否比带标签的工会更有表现力?

时间:2019-06-02 18:30:41

标签: c performance unions flexible-array-member

我正在设计一个经典的虚拟机,该虚拟机将在某种通用的,类型转换的值上运行-现在用标记的联合表示:

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,将其代表的当前胖指针的大小减半。我知道这里的简单答案是“对其进行度量”,但是我很难提出一个具有代表性的模型,而该模型本身并不是完整的实现。

第二种方法是否有名称,并且-假设将对其进行仔细管理(但假设它不会引起未定义的行为),则存在被人们广泛理解的风险:米不占?这里首选哪种方法?

顺便说一句,是否也可以类似地使用灵活数组成员?

2 个答案:

答案 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 *,就可以节省几个字节的内存。