枚举黑客在 C 中工作吗?如果是这样,它应该在 VisualStudio 2003 中工作吗?

Posted

技术标签:

【中文标题】枚举黑客在 C 中工作吗?如果是这样,它应该在 VisualStudio 2003 中工作吗?【英文标题】:does the enum hack work in C? If so, is it supposed to work in VisualStudio 2003? 【发布时间】:2013-08-01 15:10:02 【问题描述】:

我讨厌定义。为了从旧代码库中尽可能多地消除它们,我需要依靠enum-hack 来定义包含数组的结构。不幸的是,当 C 项目包含有罪的 .h 文件时,我无法编译它。

typedef struct _P_O 
    enum  MAXELEMENTS=10 ;
    P_O_U elem;
    ULONG id[MAXELEMENTS];
    USHORT nid;
 P_O, *PP_O;

这会产生错误C2208:

'type' : 没有使用此类型定义的成员 解析为的标识符 类型名称在聚合声明中,但编译器不能 声明一个成员。

OT:我讨厌使用 10 岁的编译器,还必须维护旧的 c 代码和糟糕的设计;不仅仅是定义:)

【问题讨论】:

你不能有两个称为id的元素...这是转录问题还是真正的问题? 转录错误,谢谢!!! GCC 警告:warning: declaration does not declare anything 用于enum 行。将enum 放在struct 之外就可以了。 @JonathanLeffler 的回答为我编译。 @JonathanLeffler 你应该让你的评论成为答案 【参考方案1】:

鉴于问题中的代码,GCC 会发出警告:warning: declaration does not declare anything for the enum 行。

将枚举放在结构之外,你会没事的。

typedef int P_O_U;
typedef unsigned long ULONG;
typedef unsigned short USHORT;

enum  MAXELEMENTS = 10 ;

typedef struct _P_O

    P_O_U  elem;
    ULONG  id[MAXELEMENTS];
    USHORT nid;
 P_O, *PP_O;

【讨论】:

这个解决方案的问题是 MAXELEMENTS 是全局的,如果我使用原始定义就会如此。与#define MAXELEMENTS 10 相比,此解决方案有什么优势吗? @StefanoFalasca 为什么不只是一个const static 变量? 所以您想避免#define,并且您不需要或不希望MAXELEMENTS 的值在全球范围内可见?那为什么不直接去ULONG id[19]呢? @user2485710 因为 const 静态变量是该语言的新增内容(“新”一词具有相对含义,你明白吗?:))。它在我的编译器中不存在 @AShelly 因为它需要被外部世界访问,这与它是全球性的不同。使用 enum hack,以及使用上面建议的静态 const 变量(当然,这是普通人唯一会做的事情),您可以通过 _P_O::MAXELEMENTS 访问该数字【参考方案2】:
struct foo 
    enum  MAXELEMENTS=10 ;
    long id[MAXELEMENTS];
;

像这样的枚举 hack 在 C 中是有效的(但不是一种好的代码风格,请参阅@Jonathan Leffler 的评论)。因为在定义id 时,MAXELEMENTS 符合枚举常量。

C99 6.2.1 标识符的范围

结构、联合和枚举标记的范围紧随其出现之后开始 声明标签的类型说明符中的标签。 每个枚举常量的作用域都在其定义枚举器出现在枚举器列表中之后开始。任何其他标识符的范围都在其声明符完成之后开始。

而枚举是一种整数常量。

C99 6.6 常量表达式

整数常量表达式应具有整数类型,并且只能具有整数常量、枚举常量、字符常量、结果为整数常量的 sizeof 表达式和作为强制转换的直接操作数的浮点常量的操作数。整数常量表达式中的强制转换运算符只能将算术类型转换为整数类型,除非作为 sizeof 运算符的操作数的一部分。

最后,可以在数组声明器中使用整数常量,请参阅 C99 6.7.5.2 数组声明器。这并不奇怪。

【讨论】:

您应该收到有关declaration does not declare anything 的警告。它可能会编译,但不会没有警告......我宁愿有编译没有警告的代码。 @JonathanLeffler 我同意你的观点,在没有警告的情况下编译要好得多。但是,你看,这并不总是可能的(你对我所面临的代码质量有一个粗略的了解吗?)这里的问题是 VS2003 根本不编译它。 @JonathanLeffler 我同意你的观点,我会选择不这样使用,但我认为它是有效的 C,这就是 OP 所要求的。 ISO/IEC 9899:2011, §6.7.2.1 结构和联合说明符的语法表明您可以编写struct tag int; double x; ;struct-declarator-list 是可选的)。但是,编写这样的行会产生警告。 enum 行类似——它定义了一个类型但没有向结构中添加一个成员,这是允许的,但(并非不合理地)会生成警告。所以是的,它是“合法的”C;编译器对此发出警告也是合法的,也是合理的。由于编译器对此发出警告,并且无警告编译是可取的,因此不要使用该表示法。 只是,VS2003不会警告不添加成员;它给你一个错误! :(

以上是关于枚举黑客在 C 中工作吗?如果是这样,它应该在 VisualStudio 2003 中工作吗?的主要内容,如果未能解决你的问题,请参考以下文章

纸质对话框可滚动在阴暗的dom中工作吗?

数组元素解引用和寻址 - &buffer[index] - 在 Swift 中工作吗?

Response.Redirect 可以在私有 void MVC 2 函数中工作吗?

iOS:不推荐使用的元素会继续在遗留应用程序中工作吗?

toggleClass 可以在 Safari 中工作吗? (jQuery)

Python脚本会使用pyspark在spark中工作吗