vs2017自動生成的#include“stdafx.h”詳解及解決方案
問題描述:
在高版本的Visual Studio的默認設置中,會出現這么一個現象,在新建項目之后,項目會自動生成#include“stdafx.h”的頭文件,而且刪掉之后,即使是自己正常編寫的程序也會顯示出錯:
(關於黑/深色主題,主要是為了在長時間使用電腦的時候保護眼睛,具體設置也很簡單,可以參見我另外一篇文章:)
問題解決:
實際上#include“stdafx.h”是為了方便,包含了很多頭文件的頭文件,叫做預編譯頭。這個操作在工程很大,頭文件很多的時候用起來很方便。dr我們也可以設置默認不使用預編譯頭,設置過程如下:
1.選擇【項目】-【屬性】-【C/C++】-【預編譯頭】-【創建/使用預編譯頭】
可以看到有3個選項:【創建預編譯頭】、【使用預編譯頭】和【不使用預編譯頭】。
想要取消VS2017自動生成的#include“stdafx.h”,只要將選項改為:【不使用預編譯頭】就行了。
============================================================================
以下為轉載內容(轉載自https://blog.csdn.net/qingkong8832/article/details/6695123):
1,用VS2017新建項目,選擇【Win32】-【Win32控制台應用程序】-輸入名稱:Test-【確定】
再選【下一步】-默認情況下,我們都是在【空項目】前打上對勾,建立一個純的C或C++程序。
我們這里選擇默認,即【預編譯頭】前打上對勾,之后【完成】
2,在Test項目中,頭文件有stdafx.h和targetver.h,源文件有stdafx.cpp和Test.cpp,還有一個ReadMe.txt文件。
3,默認的主函數為
- #include "stdafx.h"
- int _tmain(int argc, _TCHAR* argv[])
- {
- return 0;
- }
和我們一般的寫的程序不一樣,我們一般會寫成下面的形式:
- #include <stdio.h>
- int main()
- {
- return 0;
- }
4,我們要糾結,這里怎么沒有了stdio.h了呢,取而代之的是stdafx.h呢?
我們打開stdafx.h文件,如下:
- // stdafx.h : 標准系統包含文件的包含文件,
- // 或是經常使用但不常更改的
- // 特定於項目的包含文件
- //
- #pragma once
- #include "targetver.h"
- #include <stdio.h>
- #include <tchar.h>
- // TODO: 在此處引用程序需要的其他頭文件
可以看到,這里包含了stdio.h庫文件,為什么包含到這里呢?我們先不急着解答。
先看看,stdafx.cpp文件:
- // stdafx.cpp : 只包括標准包含文件的源文件
- // Test.pch 將作為預編譯頭
- // stdafx.obj 將包含預編譯類型信息
- #include "stdafx.h"
- // TODO: 在 STDAFX.H 中
- // 引用任何所需的附加頭文件,而不是在此文件中引用
這里面只有包含的庫文件,沒有操作,它是做什么用的呢?
在ReadMe.txt中,我們看到這么一段話:
其他標准文件:
StdAfx.h, StdAfx.cpp
這些文件用於生成名為 Test.pch 的預編譯頭 (PCH) 文件和名為 StdAfx.obj 的預編譯類型文件。
原來是生成預編譯頭文件!
5,百科上參看下:
- 一、什么是預編譯頭?
- 所謂預編譯頭,就是把頭文件事先編譯成一種二進制的中間格式,供后續的編譯過程使用。預編譯頭物理上與通常的的.obj文件是一樣的,但是千萬不要把這個中間格式與. o/.obj/.a/.lib的格式混淆,他們是截然不同的!所以預編譯頭文件的特性和目標文件也不同(盡管他們都屬於某種中間文件)。編譯入預編譯頭的.h,.c,.cpp文件在整個編譯過程中,只編譯一次,如預編譯頭所涉及的部分不發生改變的話,在隨后的編譯過程中此部分不重新進行編譯。進而大大提高編譯速度,並便於對頭文件進行管理,也有助於杜絕重復包含問題。——但也有類似的地方的,比如,它們都是編譯器之間不兼容的^_^,就是說你不能把VC生成的預編譯頭拿到GCC上去用。甚至擴展名都不一樣,VC的是大家都熟悉的. pch,而GCC的,是.gch。
- 二、什么時候使用預編譯頭?
- 當大多.c或.cpp文件都需要相同的頭文件時。
- 當某些代碼被大量重復使用時。
- 當導入某些不同庫都有實現的函數,並產生混亂時。
6,可以知道預編譯,是為了提高編譯速度!
再看下面一段話
- stdafx.h
- 1名稱的英文全稱為:Standard Application Fram Extend
- 所謂頭文件預編譯,就是把一個工程(Project)中使用的一些MFC標准頭文件(如Windows.H、Afxwin.H)預先編譯,以后該工程編譯時,不再編譯這部分頭文件,僅僅使用預編譯的結果。這樣可以加快編譯速度,節省時間。
- 預編譯頭文件通過編譯stdafx.cpp生成,以工程名命名,由於預編譯的頭文件的后綴是“pch”,所以編譯結果文件是projectname.pch。
- 編譯器通過一個頭文件stdafx.h來使用預編譯頭文件。stdafx.h這個頭文件名是可以在project的編譯設置里指定的。編譯器認為,所有在指令#include "stdafx.h"前的代碼都是預編譯的,它跳過#include "stdafx. h"指令,使用projectname.pch編譯這條指令之后的所有代碼。
- 因此,所有的MFC實現文件第一條語句都是:#include "stdafx.h"。
- 2 詳細工作原理及作用
- stdafx.h中沒有函數庫,只是定義了一些環境參數,使得編譯出來的程序能在32位的操作系統環境下運行。
- Windows和MFC的include文件都非常大,即使有一個快速的處理程序,編譯程序也要花費相當長的時間來完成工作。由於每個.CPP文件都包含相同的include文件,為每個.CPP文件都重復處理這些文件就顯得很傻了。
- 為避免這種浪費,AppWizard和VisualC++編譯程序一起進行工作,如下所示:
- ◎AppWizard建立了文件stdafx.h,該文件包含了所有當前工程文件需要的MFCinclude文件。且這一文件可以隨被選擇的選項而變化。
- ◎AppWizard然后就建立stdafx.cpp。這個文件通常都是一樣的。
- ◎然后AppWizard就建立起工程文件,這樣第一個被編譯的文件就是stdafx.cpp。
- ◎當VisualC++編譯stdafx.cpp文件時,它將結果保存在一個名為stdafx.pch的文件里。(擴展名pch表示預編譯頭文件。)
- ◎當VisualC++編譯隨后的每個.cpp文件時,它閱讀並使用它剛生成的.pch文件。VisualC++不再分析Windowsinclude文件,除非你又編輯了stdafx.cpp或stdafx.h。
- 這個技術很精巧,你不這么認為嗎?(還要說一句,Microsoft並非是首先采用這種技術的公司,Borland才是。)在這個過程中你必須遵守以下規則:
- ◎你編寫的任何.cpp文件都必須首先包含stdafx.h。
- ◎如果你有工程文件里的大多數.cpp文件需要.h文件,順便將它們加在stdafx.h(后部)上,然后預編譯stdafx.cpp。
- ◎由於.pch文件具有大量的符號信息,它是你的工程文件里最大的文件。
- 如果你的磁盤空間有限,你就希望能將這個你從沒使用過的工程文件中的.pch文件刪除。執行程序時並不需要它們,且隨着工程文件的重新建立,它們也自動地重新建立。
要點:(1), Windows和MFC的include文件都非常大,即使有一個快速的處理程序,編譯程序也要花費相當長的時間來完成工作。由於每個.CPP文件都包含相同的include文件,為每個.CPP文件都重復處理這些文件就顯得很傻了。
(2),MFC中,你編寫的任何.cpp文件都必須首先包含stdafx.h。
(3),由於.pch文件具有大量的符號信息,它是你的工程文件里最大的文件,不需要的時候可以刪除。
7,我們可以自己設置自己的預編譯文件,不一定非要是stdafx.h
右擊stdafx.cpp文件,選擇【屬性】-【C/C++】-【預編譯頭】-【創建/使用預編譯頭】
可以看到有3個選項:【創建預編譯頭】、【使用預編譯頭】和【不使用預編譯頭】。
stdafx.cpp肯定選擇的是【創建預編譯頭】
============================================================================
再右擊Test.cpp文件,選擇【屬性】-【C/C++】-【預編譯頭】-【創建/使用預編譯頭】
可見,它選擇的是【使用預編譯頭】,下面選的文件是StdAfx.h文件,最下面指明的是pch文件的路徑
================================================================================
如何創建自己的預編譯文件,其實過程正如上面我們講的過程。
如果工程很大,頭文件很多,而有幾個頭文件又是經常要用的,那么
1,把這些頭文件全部寫到一個頭文件里面去,比如寫到preh.h
2,寫一個preh.c,里面只一句話:#include "preh.h" ,為了生存pch預編譯文件
3,對於preh.c,在【屬性】里面設置【創建預編譯頭】,對於其他.c文件,設置【使用預編譯頭】
===================== End