我们正在使用纯旧的本机C语言在Windows 10 Pro(x64)上使用Visual Studio2019。昨天,我们正在研究一个废弃的小程序来测试通信链接,发现下面的代码可以编译并运行,但会混淆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编译器的角度来说)?
我想如果他们试图告诉我这个错误是我的错,我想寻找给Microsoft的标准参考(尽管我认为必须破坏其编译器或调试器,因为代码不应编译) / link还是应该正确调试,对吧?
答案 0 :(得分: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:
结构或联合标识符 opt {结构声明列表}
结构或联盟标识符
opt
下标指示标识符(在这种情况下为标签)在struct
和union
定义中是可选的。对于结构体和联合体类型的前向声明,它是必需的,但事实并非如此。从形式语法的其余部分可以看出,任何struct-or-union-specifier
都可以用来声明该类型的对象或从该对象派生的类型,例如数组类型。
此外-我怀疑这是MS调试器崩溃的原因-没有标签声明的结构或联合类型的数量没有限制。没有标签与拥有空标签是不一样的。
最终,编译器(包括Microsoft的)都接受它,而且我相当有信心,即使使用MSVC编译的版本,您也可以按预期的方式对模块错误进行处理。调试器无法正确理解变量的类型绝对是调试器中的错误。
但是请注意,Microsoft历来没有提供兼容的C编译器的意愿,他们从来没有遵循过任何C语言版本。多数情况下,MS很少或不支持的语法和功能与C ++有所不同,因为C ++一直是他们关注的焦点。