为什么Visual Studio会定义未定义的某些变量?

时间:2016-02-14 23:40:38

标签: c++ visual-studio

当我愚蠢地假设如果Visual Studio准备转到我右键单击的变量的定义时,我忍受了一个令人沮丧的几个小时试图解开某个编译器错误,然后该变量必须是定义。这就是我习惯的行为。

涉及winsvc.h的案例涉及SERVICE_STATUS。如果我成功编译了我的项目,并右键单击SERVICE_STATUS到"转到定义",那么它自然会带我到winsvc.h中的相关行。

但是,当我注释掉我的#include <winsvc.h>以便我无法成功编译时,我仍然可以右键单击我的文件中的SERVICE_STATUS,因为它不再被定义...仍然被带到winsvc.h

的行

如果我尝试用某些其他文件(特别是由我编写的文件)执行此操作 - 注释掉定义某些变量的文件也会破坏&#34;转到定义&#34;功能。这对我来说很有意义 - 如果没有定义,那就不要去了。

那么winsvc.h有什么特别之处?特别是其他文件(bug?feature?)现象适用于什么?虽然这个问题已经asked before,但没有一个答案被接受,而且就我所关注的问题而言,所有答案似乎都误解了这个问题。

1 个答案:

答案 0 :(得分:3)

首先,并且更强烈地重申@MatteoItalia的评论,IntelliSense 不是代码分析器或验证器。相反,它是一个即时的&#34;参考调度员&#34;使用 not 的快速启发式算法进行编译器级解析。这是设计 - 引用MSVC ++团队的Tag Parsing C++的Thierry Miceli(我的亮点是粗体):

  

标记解析器在Visual Studio 2010中用于填充取代NCB文件的SQL数据库。 VC ++的所有浏览功能都以某种方式依赖于标记解析器提供的结果。这些包括类视图,调用层次结构,转到定义/声明,获取所有引用,快速搜索,导航栏和VCCodeModel。

     

[...]它是一个模糊的解析器,这意味着它不是试图严格识别和验证完整的C ++语法(我们有一个很好的编译器前端来做到这一点),它懒洋洋地匹配一个输入的令牌流有一些模式。

     

[...]标记解析器不会尝试理解源代码中的每个符号或标识符。 [...] 如果声明的类型规范中的名称无法通过我们的C ++编译器解析,则这不会阻止标记解析器识别声明,它将显示在类视图中

另一点是SDF数据库是每个项目,而不是每个文件。一旦项目#include&#39; d(和used)&lt; winsvc.h&gt;中的文件,IntelliSense就会识别同一项目中任何其他文件中的SERVICE_STATUS。这很容易验证 - 只需在项目中添加一个新的空.cpp文件,然后键入SERVICE_STATUS。 &#34; 转到定义&#34;将转到&lt; winsvc.h&gt;定义,即使标题未包含在新文件中,即使文件本身根本不可编译。

最后,如果项目只包含一个文件,该文件在删除#include后不再编译,则SDF可能重建,并记住现在陈旧的引用。