扩展枚举类型添加额外值

7
什么是在C语言中扩展enum的常见做法?我有来自其他头文件的enum,想要用几个值扩展它们。希望以下示例能为我所需内容提供直观的理解。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>

enum abc { A, B, C, };     /* from some other include */
enum def { abc, D, E, F }; /* extend enum from other include */

struct thing_s {
    enum def kind;         /* use extended enum */
    union {
        unsigned n;
        char c;
        char *str;
    } data;
};

void print_thing(struct thing_s *t) {
    switch (t->kind) {
        case A:
            fprintf(stdout, "%ul\n", t->data.n);
            break;
        case B:
        case C:
        case D:
            fprintf(stdout, "%s\n", t->data.str);
            break;
        case E:
        case F:
            fprintf(stdout, "%c\n", t->data.c);
            break;
        default:
            assert(0);
    }
}

int main(int argc, char *argv[]) {

    struct thing_s t;
    t.kind = A;
    t.data.n = 1;

    print_thing(&t);

    return EXIT_SUCCESS;
}

这段代码无法编译,提示“重复的case值”错误,我理解是因为abc被视为第一个值,所以不同符号最终会有重复的整数值。


你收到该错误的原因是因为情况B和D都是相同的枚举值(1)。因此,情况标签不是唯一的。 - MFisherKDX
@MFisherKDX 是的,谢谢,我理解了错误,我只是错过了显而易见的解决方案。 - Rorschach
这个联合体有什么意义吗?你是在尝试编写一些复杂的“变体”代码吗? - Lundin
@Lundin,我不明白你的问题,那只是一个快速的例子。实际代码是由具有与枚举值对应的数据的结构体联合而成的。 - Rorschach
是的,这被称为“变量”,通常由于许多原因而不受欢迎。为了进行类型通用编程,更常见、安全和内存有效的方法是使用枚举和一个 void* 指向数据,并将其分配在结构体之外。 - Lundin
@Lundin 啊,我不知道它被称为那个。内存效率对我来说并不是一个问题,而且不必将所有东西都转换也更简单。这只是主函数中的局部变量。 - Rorschach
1个回答

7

您唯一需要关注的是将整数常量设置为唯一的。只需将第二个enum的第一个元素分配为第一个enum的最后一个元素加一即可。

enum abc { A, B, C, };     
enum def { D = C + 1, E, F }; 

8
相反地:enum abc { A,B,C,n }; enum def { D = n,E,F }; 这样常量 Cdef 之间就没有紧密耦合。将枚举中的最后一项保留为计数器而不是常量是一种常见做法。 - Lundin
@Lundin的评论将enum abc从一个只有3个可能值的枚举转换为4个可能值的枚举!不确定在abc的上下文中包含一个不应该被使用的虚拟n值是否是一个好的设计。 - Patrick Allaert
2
@PatrickAllaert 这是非常普遍的,几乎每个枚举都有一个计数器变量在末尾。另一个巨大的好处是它们可以用于确保枚举和具有命名索引的查找表之间的完整性。假设您有 const int TABLE [n] = ... - 现在您可以使用 _Static_assert(sizeof(TABLE) / sizeof(*TABLE) = n, ...。坚固、易读、安全。 - Lundin
但是,如果您正在检查覆盖率,则在使用switch语句时会遇到问题,因为现在您必须每次都考虑case abc::n,而且n在那里甚至不是真正有效的。 - nullromo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接