Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C中模拟强类型枚举?_C_Enums - Fatal编程技术网

如何在C中模拟强类型枚举?

如何在C中模拟强类型枚举?,c,enums,C,Enums,在C++03中,可以通过将其放在类(或命名空间)中进行模拟: 使用它: MyEnum::enumName v = MyEnum::VALUE_1; 有可能在C中做类似的事情吗?如果是,如何进行 我试过这样做,但不成功: struct A { enum aa { V1 = 5 }; }; int main() { A::aa a1 = A::V1; enum A::aa a2 = A::V1; struct A::aa a3 = A::V1; retur

在C++03中,可以通过将其放在类(或命名空间)中进行模拟:

使用它:

MyEnum::enumName v = MyEnum::VALUE_1;
有可能在C中做类似的事情吗?如果是,如何进行


我试过这样做,但不成功:

struct A
{
  enum aa
  {
    V1 = 5
  };
};

int main()
{
  A::aa a1 = A::V1;
  enum A::aa a2 = A::V1;
  struct A::aa a3 = A::V1;

  return 0;
}
您可以这样做:

// Declare A to use for an enumeration, and declare some values for it.
typedef struct { int i; } A;
#define A0  ((A) { 0 })
#define A1  ((A) { 1 })

// Declare B to use for an enumeration, and declare some values for it.
typedef struct { int i; } B;
#define B0  ((B) { 0 })
#define B1  ((B) { 1 })


void foo(void)
{
    // Initialize A.
    A a = A0;

    // Assign to A.
    a = A1;

    // Assign a value from B to A.
    a = B0; // Gets an error.
}

这会给您一些键入操作,但这可能会造成麻烦,具体取决于您希望对枚举及其值执行的其他操作。

这是我的解决方案。与@Eric的设计相比有一些优势:

  • 支持相等性测试(例如
    A_值\u 0==VALUE
  • 不依赖C99的复合文本
  • 可以强制转换为枚举分配不正确的值
缺点:

  • 标志不起作用(例如
    A_值0 | A_值1
  • 不能是
    开关
    'd
  • 在测试相等性时,可能会混淆IDE错误行的位置(例如,
    A_值_0==B_值_1
注:

  • 切勿取消引用此类型的指针。会导致比兰博基尼更快的车祸
以下是实现(使用
-Werror
-pedantic
编译):


由于C不提供名称空间,因此可以使用前缀

enum MyEnum {
    MyEnumA = 1,
    MyEnumB,
    MyEnumC
};

enum OtherEnum {
    OtherEnumA = 1,
    OtherEnumB
};
然后,为了变量声明的简洁性,可以为枚举声明类型,如下所示:

typedef enum MyEnum MyEnum;
typedef enum OtherEnum OtherEnum;
最后,如果您不想允许将
OtherEnumB
隐式转换为
MyEnum
类型,那么Clang提供了
-Wenum转换
标志(不幸的是,我认为GCC中没有类似的标志)


它的优点是简单、易于理解,并且可以很好地与您(至少是我的)IDE的自动完成功能配合使用。

C中没有名称空间和类,因此您不能。.在C99中,可能需要通过用下划线替换范围运算符来处理可变宏。但是在普通的C89中,我认为这是不可能的。@ AJG85:C中的结构与C++中的结构不一样,C++中它们是类,而在C中它们不是。fine@tuxtimo:实际上,C为标识符提供了四种不同的名称空间。一个用于标签,一个用于结构、联合和枚举标记,一个用于结构和联合成员,最后一个用于所有其他标识符,包括枚举常量。赋值使用C99功能(),但其余也适用于C89。@Shahbaz这对我来说适用于
gcc-ansi
(使用gcc 4.1.2)。@rwos,啊,是的。我现在记得我不能写它(在我的一些代码中),因为我是用g++编译的,而不是说它是C11。我的错。这里的大问题是平等性测试不起作用,即A=A0;A b=A0;bool-foo=(a==b)不编译。此外,您不能在开关中使用类型A的变量。@EricFinn gcc with
-ansi-pedantic
显示警告(“ISO C90禁止复合文字”)。另一方面:谁只使用C89/90编译了?:-)+1,一些注释:我仍然会使用底部的
enum
来声明值。如果添加了值,则更易于维护,例如,为了避免某些旧编译器出现令人毛骨悚然的整数到指针警告,您应该查看
uintpttr\u t
,类似于
((B)(uintptpr\u t)0x2)
。要声明指向
struct
的指针,甚至不必声明结构本身,
typedef struct spooky\u struct*a
就足够了。这种方法依赖于协作实现定义的行为“整数可以转换为任何指针类型…”。。。,结果是实现已定义,可能未正确对齐,可能未指向引用类型的实体,并且可能是陷阱表示。“C17dr§6.3.2.3 5边缘编码。我知道这是3年后的事了,所以如果没有回复,不用担心。您使用的是g++吗?有了gcc,我就无法实现这一点。我尝试了4.6和4.7版本,还添加了-Wextra,-Wall-Wenum compare。我使用了叮当。我假设GCC也会为
enum
类型之间的隐式转换发出警告,但我可能错了。看起来GCC只在使用
-Wenum compare
时发出比较警告。啊,对了。它的工作原理和你描述的一样。我也尝试了最近的gcc,但仍然没有警告。也有bug报告和讨论,但gcc开发人员似乎对现状感到满意,因为“标准说所有这些都是有效的”。
enum MyEnum {
    MyEnumA = 1,
    MyEnumB,
    MyEnumC
};

enum OtherEnum {
    OtherEnumA = 1,
    OtherEnumB
};
typedef enum MyEnum MyEnum;
typedef enum OtherEnum OtherEnum;
/tmp/test.c:24:20: warning: implicit conversion from enumeration type 'enum OtherEnum' to different enumeration type 'MyEnum' (aka 'enum MyEnum') [-Wenum-conversion]
    MyEnum value = OtherEnumB;
           ~~~~~   ^~~~~~~~~~
1 warning generated.