c - C 中的匿名结构

标签 c visual-studio debugging

我们正在 Windows 10 Pro (x64) 上使用普通旧的 native 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 的示例中是硬编码的),调试器将在显示变量值的工具提示中显示两个匿名结构之一的错误成员变量名称和值,并且在监 window 口中显示指定的变量。

我的问题是:除了这是一种糟糕的编码实践之外,还有什么原因导致此代码错误(严格来说是 C 编译器意义上的)?

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

最佳答案

My question is: Other than it being a bad coding practice, is there any reason why this code is wrong (strictly in a C compiler sense)?

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

例如,这种方式就比较常见:

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

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

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

I guess I'm interested in finding the standard reference to give Microsoft if they try to tell me that this bug is my fault (though I believe that either their compiler or debugger must be broken, since the code should either not compile/link or should debug correctly, right?)

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

结构或 union 说明符:
结构或 union 标识符opt { struct-declaration-list }
结构或 union 标识符

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

此外——我怀疑这就是 MS 调试器失败的地方——对于没有标签声明的结构或 union 类型的数量没有限制。没有标签与有空标签不同。

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

但是请注意,Microsoft 历来没有表现出提供符合标准的 C 编译器的意愿,他们的编译器从未符合任何版本的 C 语言。大多数情况下,MS 很差或不支持与 C++ 不同的语法和功能,因为 C++ 一直是他们的重点。

关于c - C 中的匿名结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56079777/

相关文章:

c - 如何同时正确使用管道和信号?

java - 使用数组的 JNI 任务

c - 带成员的整个结构的大小

vb.net - VB为什么说文件正在使用

c++ - 调试 gdb 设置

javascript - 为什么调试器不在断点处停止?

c - 将 cmp 与进程替换 (stdout) 一起使用? ( bash )

c++ - 非常慢的 ffmpeg/sws_scale() - 仅在重载时

visual-studio - LNK2005 将静态 openCV 库与 Visual Studio 和 QT Creator 链接时出错

java - 在 Eclipse 中一次运行多个调试实例