【问题标题】:Anonymous structs in CC中的匿名结构
【发布时间】:2019-09-28 11:47:51
【问题描述】:

我们在 Windows 10 Pro (x64) 上使用普通旧的原生 C 语言使用 Visual Studio 2019。昨天我们正在开发一个小程序来测试通信链接,发现下面的代码可以编译并运行,但混淆了 VS2019 调试器:

#include <Windows.h>
#include <stdio.h>
#include <string.h>

struct
{
   char *label;
   int   value;
} one[2] =
{
   { "one", 1 },
   { "two", 2 },
};

struct
{
   int   prox;
   DWORD fuse;
   float debug;
} two[6];

int main( int argc, char **argv )
{
   DebugBreak();
   return 0;
}

当处于断点时(在我们给 Microsoft 的示例中硬编码),调试器将在显示变量值的工具提示中显示两个匿名结构之一的错误成员变量名称和值,并在监视窗口中显示指定的变量。

我的问题是:除了它是一种糟糕的编码习惯之外,还有什么理由说明这段代码是错误的(严格来说,在 C 编译器意义上)?

如果他们试图告诉我这个错误是我的错,我想我有兴趣找到给微软的标准参考(尽管我相信他们的编译器或调试器必须被破坏,因为代码不应该编译/link 或者应该正确调试,对吧?)

【问题讨论】:

  • 我什至看不出这是一个“坏习惯”。唯一不好的做法是使用 MSVC 并希望它符合一些 C 标准...
  • 这有点模糊。您能否更具体地说明您遇到的错误?
  • 但是,我可以在 VS2017 中重现此代码的任何问题。工具提示显示正确的值。观察窗口显示正确的值。一切看起来都很好。你用的是什么版本?
  • @AnT 这是 C,char* 是不好的做法,但没有错。
  • 哦,我的错。我错过了 [C] 标签。但是,调试器在 C 版本中也能正确显示所有内容。另外,请注意,如果您将鼠标指针指向[2] 部分中的括号之一,工具提示将显示one[2] 表达式的值,这显然是垃圾。如果您将鼠标指向one,它们将正确显示数组中的值。同样的行为也适用于第二个数组。

标签: c visual-studio debugging


【解决方案1】:

我的问题是:除了它是一种糟糕的编码习惯之外,还有什么原因导致这段代码是错误的(严格来说是 C 编译器)?

我不一定同意代码表现出不良做法。这当然是有效的,因为结构类型不需要在 C 中用标签声明。没有标签的结构类型不能在它们出现的声明之外直接引用,但它们可以很好地用于声明对象,并且它们更常用在 typedef 和更大的结构中。

比如这种方式比较常见:

typedef struct {  // <-- no tag
    char *label;
    int   value;
} struct_one;

struct_one one[2] = {
    { "one", 1 },
    { "two", 2 }
};

毕竟,如果你不打算通过标签来引用类型,那为什么要在标签命名空间中引入一个呢?

我想我有兴趣找到标准参考 Microsoft 如果他们试图告诉我这个错误是我的错(尽管我 相信他们的编译器或调试器必须被破坏,因为 代码不应该编译/链接或应该正确调试, 对吧?)

嗯,有这个C's formal grammar specification:

struct-or-union-specifier:
struct-or-union identifier<sub>opt</sub> { struct-declaration-list }<br>struct-or-union identifier

opt 下标表示标识符(在本例中为标记)在struct 和union 定义中是可选的。它是结构和联合类型的前向声明所必需的,但这不是你的情况。从形式语法的其余部分可以看出,任何struct-or-union-specifier 都可以用于声明该类型的对象或从它派生的类型,例如数组类型。

此外——我怀疑这是MS调试器失败的地方——没有标签声明的结构或联合类型的数量没有限制。没有标签和有一个空标签是不一样的。

最终,编译器(包括 Microsoft 的)接受它,而且我相当有信心您会发现即使是 MSVC 编译的版本也能按预期运行,模数程序错误。调试器不能正确理解变量类型肯定是调试器的一个bug。

但是请注意,Microsoft 历来很少愿意提供符合标准的 C 编译器,他们的编译器从未符合 C 语言的任何版本。大多数情况下,MS 不支持或不支持 C++ 的语法和特性与 C++ 不同,因为 C++ 一直是他们关注的焦点。

【讨论】:

  • 最后一段完全不正确。 MSVC 一直被认为是市场上最好的 C89/90 编译器之一。对于 C 编译器的一般状态,无论他们遇到什么不合规问题(在质量和数量上)都是典型的。从 2000 年初开始的关于“C++ 一直是他们的焦点”的互联网假货早已被推翻和遗忘。现代 MSVC 支持 C99,只有一些遗漏(最显着的是 VLA)。
猜你喜欢
  • 2013-04-18
  • 2020-10-28
  • 2016-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-23
  • 2013-05-19
  • 1970-01-01
相关资源
最近更新 更多