为什么在有条件地包含stdafx.h后我收到编译错误?

9
我正在尝试编写一个可以在Borland C++和Visual C++中编译的程序。为此,在源代码在VS下编译时,我添加了#ifdef _MSC_VER来包含stdafx.h文件。该代码可以在Borland C++中编译并执行正常,但在VS下会失败:

错误C1020:意外的#endif

#ifdef _MSC_VER //I'm in VS
#include "stdafx.h"
#endif //this line doesn't compile in VS


#ifdef __BORLANDC__   //I'm in Borland
#pragma hdrstop
#pragma argsused
#endif

#include <iostream>

int main(int argc, char* argv[])
{
    std::cout << "Hello" << std::endl;
    std::cin.get();
    return 0;
}

我该如何修复这个错误?
4个回答

13
MSVC实现预编译头文件的方式基本上是编译器忽略掉引入预编译头文件之前的一切内容,并从那里重新开始。因此,当您编译程序时,它不会“记住”#ifdef行,所以#endif行对它来说没有意义。
事实上,除了特殊的命名方案(无论如何都可以更改)之外,“stdafx.h”与“MS”无关。那么为什么要在第一次阻止Borland的包含呢?最坏的情况是,您将_MSC_VER块移入头文件中,然后您将处于与现在相同的情况,只是多了一个无用的包含文件。或者,让您的构建系统重定向#include到特定于Borland的stdafx.h文件。

2
那一定是预编译头文件的特性所起的作用。简单的解决方案是在VS项目设置中将其关闭。 问题在于,当编译器遇到

时会重置其状态。
#include "stdafx.h"

将代码中的状态保存到预编译头文件中。因此,#ifdef...行变为被忽略,而#endif行会导致编译器错误。


0
如果我们将编译器条件切换到stdafx.h中,就可以避免这个错误。例如,以下代码行可以在stdafx.h中定义。
    ********************* stdafx.h **************************
    #pragma once

    #if defined (_MSC_VER)

    #include "targetver.h"

    #define WIN32_LEAN_AND_MEAN             
    // Windows Header Files:
    #include <windows.h>
    #endif 
    *********************************************************

您可以根据需要在此宏条件语句中切换pragma once或传统的头文件保护。 因此,我们能够使用任何C/C++编译器构建stdafx.h,因为我们将宏条件语句移植到stdafx.h中。


0

其他人评论了PCH问题。另外,在Borland中,必须将#pragma argsused附加到函数上。它的目的是向编译器单独指出函数的参数不被函数体使用,因此不会发出“未使用的参数”警告。因此,您不能在同一个#ifdef块中分组#pragma hdrstop#pragma argsused。您需要将它们分开,例如:

#include "stdafx.h"

#ifdef __BORLANDC__
#pragma hdrstop
#endif

#include <iostream>

#ifdef __BORLANDC__
#pragma argsused
#endif
int main(int argc, char* argv[])
{
  std::cout << "Hello" << std::endl;
  std::cin.get();
  return 0;
}

一个更简单的解决方案是直接注释掉参数名称:
#include "stdafx.h"

#ifdef __BORLANDC__
#pragma hdrstop
#endif

#include <iostream>

int main(int /*argc*/, char* /*argv[]*/)
{
  std::cout << "Hello" << std::endl;
  std::cin.get();
  return 0;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接