【问题标题】:Verify that all set values of an enum are distinct验证枚举的所有设置值是否不同
【发布时间】:2015-06-24 09:21:08
【问题描述】:

我最近才发现,在设置枚举变量的值时,多个变量可以具有相同的值。例如,下面的代码是完全正确的:

enum my_enum
{
    A = 3,
    B = 4,
    C = 3,
    D = 5
};

但是,在我的框架中,我必须手动设置每个变量,因为它用于将错误代码传达给其他系统。如果不要求其他团队也进行修改,我无法更改错误代码的值。

我将所有错误代码重新组合到一个枚举中,以确保我们不会因为不同的原因重用相同的错误代码(以前就是这种情况)。但是现在,没有什么能阻止任何人为不同的错误重用相同的值。

如果我将相同的值分配给枚举中的不同名称,有没有办法让编译器返回错误?

我可以使用 gcc 或 clang 进行编译。

【问题讨论】:

  • 您可以编写一个单元测试来检查给定枚举中所有整数值的唯一性。
  • 最好不要明确指定值,除了第一个值。

标签: c enums compilation


【解决方案1】:

switch 语句不能有两个具有相同值的案例。所以你可以在某个地方有一个开关。不使用 default: 大小写,gcc 会警告您,如果您添加新值,则不会在 switch 语句中处理枚举成员。如果枚举的两个值相同,编译会失败。

一些例子:

typedef enum {
    ERR_NONE = 0,
    ERR_SAME = 0
} err_t;

volatile err_t e = ERR_NONE;

int main( int argc, char* argv[] )
{
    switch( e )
    {
        case ERR_NONE:
        break;

        case ERR_SAME:
        break;
    }

    return 0;
}

gcc -Wall switch.c 给出:

switch.c: In function 'main':
switch.c:16:9: error: duplicate case value
     case ERR_SAME:
     ^
switch.c:13:9: error: previously used here
     case ERR_NONE:
     ^

还有……

typedef enum {
    ERR_NONE = 0,
    ERR_NEXT,
    ERR_MISSING,
} err_t;

volatile err_t e = ERR_NONE;

int main( int argc, char* argv[] )
{
    switch( e )
    {
        case ERR_NONE:
        break;

        case ERR_NEXT:
        break;
    }

    return 0;
}

gcc -Wall switch-missing.c 给出:

switch-missing.c: In function 'main':
switch-missing.c:12:5: warning: enumeration value 'ERR_MISSING' not handled in switch [-Wswitch]
 switch( e )
 ^

【讨论】:

  • 很好,我不知道开关上的重复大小写警告。我想我可以做一个对所有值进行切换的单元测试,但这会使我重复代码,我需要一个非常好的评论来确保没有人添加默认值:无论如何感谢你的回答!
  • 只需将其放入您的代码中即可。您会收到警告 - 即使代码因为未使用而被链接器丢弃。
  • @DainDwarf 警告应该在您的评论中读取错误。如果 switch 中有重复的 case,代码编译将失败,如果 ENUM 中有条目但 switch 中不存在,则会发出警告
  • 您可以使用宏来生成枚举和带有开关的函数,但是,在 C 中,宏的语法不会很好。我认为您最终将不得不做类似ENUM(Type, (Name0, Value0), (Name1, Value1)) 等的事情。如果您完全可以使用C++,您可以获得更好的语法,例如ENUM(Type, Name0 = Value0, Name1 = Value1)。如果您有兴趣,请在 SO 中搜索“enum to string”以获取有关如何开始的一些想法。如果您的项目可以接受这种方法,我也可以举一个小例子。
猜你喜欢
  • 2011-11-14
  • 2010-09-06
  • 2017-12-14
  • 1970-01-01
  • 2014-09-19
  • 1970-01-01
  • 2020-05-07
  • 2019-07-08
  • 2017-08-26
相关资源
最近更新 更多