8

我正在嘗試編寫一個在Borland C++和Visual C++中編譯的程序。要做到這一點,我添加#ifdef _MSC_VER包括stdafx.h文件,當源編譯在VS.代碼編譯和Borland的C++執行OK,但在VS,它失敗:爲什麼我有條件地包含stdafx.h後會出現編譯錯誤?

錯誤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; 
} 

如何解決這個問題?

回答

11

MSVC實現預編譯頭的方式,基本上是編譯器會忽略一切都交給在預編譯的頭帶來的線,並從頭開始出現了。所以當你編譯你的程序時,它不會「記住」#ifdef行,所以#endif行對它沒有意義。

事情是,除了特殊的命名方案[你可以改變任何方式],stdafx.h沒有固有的「MS」。那麼爲什麼要在第一時間阻止Borland的包含呢?在最壞的情況下,您將_MSC_VER塊移動到標題中,並且最終會出現與現在相同的情況,除非有一個浪費的包含文件。或者讓您的構建系統將#include重定向到Borland特定的stdafx.h文件。

2

這必須是預編譯頭部特徵效果。簡單的解決方案是在VS項目設置中關閉它。 問題是,當它遇到

#include "stdafx.h" 

行保存在預編譯的頭文件中的狀態編譯器復位其狀態。所以#ifdef...線變得ignored#endif行導致編譯器錯誤

1

其他人對PCH問題發表了評論。在另一個說明中,在Borland中,#pragma argsused必須附加到一個函數中。它的目的是單獨給編譯器函數的參數不被函數體使用,所以它不會發出「未使用的參數」警告。因此,您不能將#pragma hdrstop#pragma argsused組合在同一個#ifdef區塊中。你需要將它們分開,如:

#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; 
} 

一個simplier解決方案是簡單註釋掉參數名稱代替:

#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; 
} 
5

如果開關編譯器中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,因爲我們移植了我們的宏條件語句intostdafx.h

相關問題