3

我遇到了一些这样的 C 代码问题:

struct SomeType { ...details immaterial... };

static struct SomeType array[] =
{
    { ... },
    ...
    { ... },
};
enum { ARRAY_SIZE = sizeof(array) / sizeof(array[0]) };

Unix 编译器(各种版本的 GCC,以及 AIX 和 HP-UX 上的编译器)都对enum. MSVC 2005 以错误反对C2056: Illegal Expression。根据MSDN,这是因为“由于先前的错误,表达式无效”。这是报告的唯一错误,这有点令人惊讶。

但是,我的问题是:

  1. MSVC 2005 是否准确解释了 C89 标准以禁止enum?
  2. Unix 编译器是否过于慷慨地允许这样做而不发出警告?
  3. C99(或 C2011)有什么不同吗?
  4. 更新版本的 MSVC 是否仍然反对enum?

FWIW:可接受的解决方案是将其更改enum为:

static int const ARRAY_SIZE = sizeof(array) / sizeof(array[0]);

不推荐使用的选项很麻烦

Michael Burr提供了一些非常有价值的额外信息,让我能够解决问题。

可编译示例(与实际问题同构):

static const char *names[] = { "abc", "def", "ghi" };
enum { NAMES_SIZE = sizeof(names) / sizeof(names[0]) };

static const struct stuff { const char *name; int flags; } array[] =
{
    { "abc", 1 },
    { "def", 2 },
    { "ghi", 3 },
};
enum { ARRAY_SIZE = sizeof(array) / sizeof(array[0]) };

MSVC 的精确版本(由 给出cl)是:

Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86

这就是迈克尔所说的版本。

而且,我找到了问题的原因。(下面的命令行删除了所有项目特定的花言巧语——示例代码不需要的大量 /D 和 /I 选项。)编译:

cl     /W3 /c /LD /MD /Od aaa.c

上面的代码编译OK。

cl /Zg /W3 /c /LD /MD /Od aaa.c

这首先会生成警告:

cl : Command line warning D9035 : option 'Zg' has been deprecated and will be removed in a future release

一年或更长时间以来,我一直在抱怨使用不推荐使用的选项进行编译,但负责这个子项目的团队中没有人愿意站出来修复它,我不应该——即将改变的事情。

然后它说:

aaa.c(2) : error C2056: illegal expression
aaa.c(10) : error C2056: illegal expression

因此,不仅该/Zg选项已被弃用,而且它也是造成问题的首要原因。现在我有更好的弹药来追击人了!

感谢您提供额外的信息,迈克尔。

PS:关于 MSDN 页面/Zg说:

如果您使用该/Zg选项并且您的程序包含具有 、 或 类型(或指向此类类型的指针)的形式参数,则struct每个enumunion或 类型的声明都struct必须enum具有union标记(名称)。

这并不完全准确。示例片段中没有形式参数,并且这些enum值从未传递给函数。但是如果没有 上的标签enum,错误仍然会与/Zg标志一起出现。


(不;我并不是特别喜欢 MSVC 2005。我工作的小组还没有升级到任何更新的版本。大多数情况下它不会影响我。在某些情况下,像这样,当它很痛时。有一天,我会弄清楚为什么 Windows 上的其他构建似乎接受enum. )

这是严格的 C 代码。MSVC 标记是 Visual-C++ 标记的同义词。

4

1 回答 1

2

这在 C89 中当然是合法的(只要结果数组大小可以表示为int)。

§3.5.2.2 中对枚举常量定义值的约束是:

定义枚举常量值的表达式应为整数常量表达式,其值可表示为 int。

§3.4 描述了整数常量表达式:

约束

常量表达式不应包含赋值、递增、递减、函数调用或逗号运算符,除非它们包含在 sizeof 运算符的操作数中。

每个常量表达式都应计算为一个常量,该常量在其类型的可表示值范围内。

语义

在多个上下文中需要计算结果为常量的表达式。如果在翻译环境中计算表达式,则算术精度和范围应至少与在执行环境中计算表达式一样大。

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

于 2012-03-27T06:08:24.423 回答