C / C ++枚举:检测多个项目映射到相同值时 [英] C/C++ enums: Detect when multiple items map to same value

查看:196
本文介绍了C / C ++枚举:检测多个项目映射到相同值时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有编译时检测/防止C / C ++枚举中的重复值?



捕获是有多个项目被初始化为显式值



背景



我继承了一些C代码,如下所示:









MsgFoo1A = BASE1_VAL(5)
$ b ,// 5
MsgFoo1B,// 6
MsgFoo1C,// 7
MsgFoo1D,// 8
MsgFoo1E,// 9
MsgFoo2A = BASE2_VAL,//呃哦7再次...
MsgFoo2B //呃哦! 8再次...
} FOO;

问题是随着代码的增长作为开发人员向 MsgFoo1x 组添加更多消息,最终超过 BASE2_VAL



这段代码最终将被迁移到C ++,所以如果有一个C ++的解决方案(模板魔术?),那没关系 - 但是一个适用于C和C ++的解决方案更好。

解决方案

有几种方法来检查这个编译时间,但是它们可能并不总是适合你。首先在MsgFoo2A之前插入一个标记枚举值。

  typedef枚举
{
MsgFoo1A = BASE1_VAL,
MsgFoo1B,
MsgFoo1C,
MsgFoo1D,
MsgFoo1E,
MARKER_1_DONT_USE,/ *不要使用此值,但将其留在此处。 * /
MsgFoo2A = BASE2_VAL,
MsgFoo2B
} FOO;

现在我们需要一种方法来确保 MARKER_1_DONT_USE< BASE2_VAL 在编译时。有两种常见的技术。



负数大小数组



声明一个负数大小的数组是一个错误。这看起来有点丑陋,但它有效。

  extern int IGNORE_ENUM_CHECK [MARKER_1_DONT_USE> BASE2_VAL? -1:1]; 

如果MARKER_1_DONT_USE大于BASE_2_VAL,几乎所有编写的编译器都会生成错误。 GCC吐出来:

  test.c:16:错误:数组IGNORE_ENUM_CHECK的大小为负



静态断言



如果您的编译器支持C11, code> _Static_assert 。对C11的支持并不普及,但您的编译器可能支持 _Static_assert ,特别是因为C ++中的相应功能得到广泛支持。

  _Static_assert(MARKER_1_DONT_USE< BASE2_VAL,枚举值重叠); 

GCC发出以下消息:

  test.c:16:1:错误:静态断言失败:枚举值重叠。 
_Static_assert(MARKER_1_DONT_USE< BASE2_VAL,枚举值重叠);
^


Is there a compile-time way to detect / prevent duplicate values within a C/C++ enumeration?

The catch is that there are multiple items which are initialized to explicit values.

Background:

I've inherited some C code such as the following:

#define BASE1_VAL    (5)
#define BASE2_VAL    (7)

typedef enum
{
  MsgFoo1A = BASE1_VAL,       // 5
  MsgFoo1B,                   // 6
  MsgFoo1C,                   // 7
  MsgFoo1D,                   // 8
  MsgFoo1E,                   // 9
  MsgFoo2A = BASE2_VAL,       // Uh oh!  7 again...
  MsgFoo2B                    // Uh oh!  8 again...
} FOO;

The problem is that as the code grows & as developers add more messages to the MsgFoo1x group, eventually it overruns BASE2_VAL.

This code will eventually be migrated to C++, so if there is a C++-only solution (template magic?), that's OK -- but a solution that works with C and C++ is better.

解决方案

There are a couple ways to check this compile time, but they might not always work for you. Start by inserting a "marker" enum value right before MsgFoo2A.

typedef enum
{
    MsgFoo1A = BASE1_VAL,
    MsgFoo1B,
    MsgFoo1C,
    MsgFoo1D,
    MsgFoo1E,
    MARKER_1_DONT_USE, /* Don't use this value, but leave it here.  */
    MsgFoo2A = BASE2_VAL,
    MsgFoo2B
} FOO;

Now we need a way to ensure that MARKER_1_DONT_USE < BASE2_VAL at compile-time. There are two common techiques.

Negative size arrays

It is an error to declare an array with negative size. This looks a little ugly, but it works.

extern int IGNORE_ENUM_CHECK[MARKER_1_DONT_USE > BASE2_VAL ? -1 : 1];

Almost every compiler ever written will generate an error if MARKER_1_DONT_USE is greater than BASE_2_VAL. GCC spits out:

test.c:16: error: size of array ‘IGNORE_ENUM_CHECK’ is negative

Static assertions

If your compiler supports C11, you can use _Static_assert. Support for C11 is not ubiquitous, but your compiler may support _Static_assert anyway, especially since the corresponding feature in C++ is widely supported.

_Static_assert(MARKER_1_DONT_USE < BASE2_VAL, "Enum values overlap.");

GCC spits out the following message:

test.c:16:1: error: static assertion failed: "Enum values overlap."
 _Static_assert(MARKER_1_DONT_USE < BASE2_VAL, "Enum values overlap.");
 ^

这篇关于C / C ++枚举:检测多个项目映射到相同值时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆