stdafx.h和targetver.h的作用

本文介绍预编译头文件stdafx.h的工作原理及其在MFC项目中的应用,以及如何通过targetver.h定义程序的目标运行环境。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

stdafx.h和targetver.h的作用

1 stdafx.h作用及原理

1.1 简介

stdafx.h名称的英文全称为:Standard Application FrameworkExtensions

所谓头文件预编译,就是把一个工程(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"

1.2 详细工作原理及作用

   stdafx.h中没有函数库,只是定义了一些环境参数,使得编译出来的程序能在32位的操作系统环境下运行。

   Windows和MFC的include文件都非常大,即使有一个快速的处理程序,编译程序也要花费相当长的时间来完成工作。由于每个.CPP文件都包含相同的include文件,为每个.CPP文件都重复处理这些文件就显得很傻了。为避免这种浪费,AppWizard和VisualC++编译程序一起进行工作,如下所示:

  (1)AppWizard建立了文件stdafx.h,该文件包含了所有当前工程文件需要的MFCinclude文件。且这一文件可以随被选择的选项而变化。

        具体在stdafx.h中需要include什么头文件,取决于用户在AppWizard中的选择.
        比如:

#include <afxwin.h>         // MFC core and standard components

#include <afxext.h>           // MFC extensions

#include <afxole.h>         // MFC OLE classes

#include <afxodlgs.h>     // MFC OLE dialog classes

#include <afxdisp.h>        // MFC Automation classes

  (2)AppWizard然后就建立stdafx.cpp。这个文件通常都是一样的。

  (3)然后AppWizard就建立起工程文件,这样第一个被编译的文件就是stdafx.cpp

  (4)当VisualC++编译stdafx.cpp文件时,它将结果保存在一个名为stdafx.pch的文件里。

             (扩展名pch表示预编译头文件。)

  (5)当VisualC++编译随后的每个.cpp文件时,它阅读并使用它刚生成的.pch文件。VisualC++不再分析                                     Windowsinclude文件,除非你又编辑了stdafx.cpp或stdafx.h。

  

       这个技术很精巧,你不这么认为吗?(还要说一句,Microsoft并非是首先采用这种技术的公司,Borland才是。)在这个过程中你必须遵守以下规则:

  ◎你编写的任何.cpp文件都必须首先包含stdafx.h。

  ◎如果你有工程文件里的大多数.cpp文件需要.h文件,顺便将它们加在stdafx.h(后部)上,然后预编译stdafx.cpp。

  ◎由于.pch文件具有大量的符号信息,它是你的工程文件里最大的文件。

  如果你的磁盘空间有限,你就希望能将这个你从没使用过的工程文件中的.pch文件删除。执行程序时并不需要它们,且随着工程文件的重新建立,它们也自动地重新建立。

 

       stdafx.h文件中包含了一些必要的头文件(如afxwin.h),对应于stdafx.h有一个stdafx.cpp文件,该文件内包含一句:#include "stdafx.h",其作用是令编译器编译出一个stdafx.obj预编译头文件(pre-compile header,需要设置编译选项),在下次编译时以降低总的编译时间。若使用ClassWizard定义新类,则有可能在stdafx.h中增加新的 include files。比如,若选用MFC template classes,stdafx.h中便会增加:#include <afxtempl.h>。

注:

1.afxwin.h是MFC编程的必需文件,其中包含如CString,CEdit类运行所必需的头文件,最好保证该句在头文件首行;它还会调用windows.h,改头文件包含有数据类型的定义、API入口点定义和其它有用的参数信息。


2.非MFC工程使用MFC库时最常见的问题就是windows.h重复包含错误:fatalerror C1189: #error :  WINDOWS.H alreadyincluded.  MFC apps must not #include<windows.h>;


3.#define WIN32_LEANAND_MEAN,在windows的头文件中拒绝接受MFC类库,以加速编译时间;


4.afx - afx中的af指的是Application Frame的缩写,曾经有一个技术开发团队专门作ApplicationFrame,后来给这个团队命名用afx,x本身没有含义,只不过构成一个响亮的口号,后来就一直沿用下来。


5.

#if _MSC_VER > 1000                      //表示版本

#pragma once                             //避免头文件之间的相互包含

#endif // _MSC_VER > 1000

6.建立了一个新的空的工程,项目中的stdafx.cpp使用的是CreatePrecompiled Header (/Yc),而其它.cpp是用的Use Precompiled Header (/Yu),并且Create/Use PCHTrhough File都是stdafx.h

1.3 总结

   通俗一点说,当我们使用AppWizard来自动生成某些项目的时候,系统会自动把所需要include的头文件在stdafx.h中先include一下,这样,我们只需要直接include这个stdafx.h文件即可.因为同一个项目中的不同源文件CPP都包含相同的include文件,这样,为每个.CPP文件都重复include这些文件就显得很傻了。当然如果你不用MFC的话就不用了。即:在每个.cpp文件中都include stdafx.h 就相当于包含了其他的如iostream.h等文件

   与stdio.h的区别

  我们一般用TC或vc编译C程序的时候都要首先包含这个stdio.h头文件,这个头文件里面包含了scanf和printf函数的定义,如果我们不在程序开头include这个文件,那么你调用上面这两个函数就不会成功,它其实和c++中的iostream.h文件的作用差不多的,它们一般都已经在stdafx.h文件中被包含。


 

targetver.h的作用

定义程序运行的环境,如限制程序只能在XP下运行,限制程序在只能在Vin7下运行,或限制程序只能在XP以上系统运行,或限制程序只能在Server2003以上系统运行...

用法:

#ifndef WINVER                	  //程序中没有定义WINVER宏时

#define WINVER 0x0600            // 定义WINVER为0x0600    //0x0600表示Windows Vista

#endif

 #ifndef _WIN32_WINNT                // 程序中没有定义_WIN32_WINNT宏时

#define _WIN32_WINNT 0x0600     // 定义_WIN32_WINNT为0x0600    //0x0600表示Windows Vista

#endif


附:

0×0500 表示Windows 2000

0×0501Windows XP

0×0502Windows Server 2003

0×0600  Windows Vista

<think>我们正在处理的是关于预编译头文件的警告问题,具体是:`warning C++ #include <math.h> skipped when looking for precompiled header, add to stdafx.h or rebuild precompiled header` 根据引用[1]引用[2]的内容,该警告发生在Visual Studio环境中,主要原因是预编译头文件的使用配置问题。 问题分析: 在Visual Studio项目中,如果启用了预编译头(通常为`stdafx.h`),则每个源文件(.cpp)应该首先包含`stdafx.h`(或指定的预编译头文件)。如果某个源文件在包含预编译头文件之前包含了其他头文件(如`math.h`),则编译器会跳过这些头文件,并给出警告。 解决方案有两种: 1. 将`#include <math.h>`添加到预编译头文件(如`stdafx.h`)中,这样在预编译头时就会包含`math.h`,后续所有源文件都可以使用。 2. 在每个源文件中,确保在包含其他头文件之前先包含预编译头文件。 具体步骤: 方法一:将math.h添加到预编译头文件(推荐) 1. 打开项目中的预编译头文件(通常是`stdafx.h`或`pch.h`,取决于项目设置)。 2. 在预编译头文件中添加`#include <math.h>`。 3. 重新生成预编译头(重新编译整个项目即可,或者单独重新编译预编译头文件)。 方法二:调整源文件的包含顺序(如果不想修改预编译头) 1. 确保每个出现警告的源文件(.cpp)的第一行有效代码是包含预编译头文件,例如: ```cpp #include "stdafx.h" // 或者项目使用的预编译头文件名 ``` 然后再包含其他头文件,例如: ```cpp #include <math.h> ``` 2. 注意:如果源文件已经包含了预编译头文件,但是`#include <math.h>`写在预编译头文件之前,则移动它到预编译头包含之后。 另外,如果项目使用的是新的预编译头文件(如Visual Studio 2017及以上版本的`pch.h`),则对应修改。 如果不想使用预编译头,可以关闭它(不推荐,因为预编译头可以加速编译): 1. 项目属性 -> 配置属性 -> C/C++ -> 预编译头 -> 预编译头:选择“不使用预编译头”。 2. 注意:关闭后编译时间可能会变长。 根据引用[2]的提示,还可以检查附加包含目录(Additional Include Directories)是否设置正确,确保`math.h`所在的目录在包含路径中(通常标准库会自动包含)。 完整步骤示例(方法一): 1. 打开`stdafx.h`(或`pch.h`)文件。 2. 在文件末尾(或合适位置)添加: ```cpp #include <math.h> ``` 3. 保存文件,重新生成整个项目。 示例代码(stdafx.h): ```cpp // stdafx.h: 标准系统包含文件的包含文件, // 或是经常使用但不常更改的 // 特定于项目的包含文件 // #pragma once #include "targetver.h" #include <stdio.h> #include <tchar.h> // 添加math.h #include <math.h> // 添加这一行 ``` 重新编译后,警告应该消失。 注意事项: - 如果项目中多个源文件都需要使用`math.h`,将其添加到预编译头中是最有效的方法。 - 如果只有少数源文件使用`math.h`,且不想修改预编译头,则在这些源文件中调整包含顺序。 引用[1]中提到的错误`fatal error C1010`是因为在寻找预编译头时遇到了文件结束,即源文件没有包含预编译头文件。所以,确保每个源文件都包含了预编译头文件(如果项目启用了预编译头)。 相关问题: 1. 如何正确使用预编译头文件来加速编译? 2. 在Visual Studio中如何关闭预编译头? 3. 预编译头文件包含哪些内容比较合适? 4. 为什么在包含预编译头之前包含其他头文件会被跳过?</think>### 解决预编译头文件中`math.h`被跳过的警告问题 #### 问题分析 当出现警告 `#include <math.h> skipped when looking for precompiled header` 时,表示编译器在预处理阶段跳过了`math.h`头文件。这通常发生在使用预编译头(如`stdafx.h`)的Visual Studio项目中,原因有二: 1. **未在预编译头中包含`math.h`** 预编译头机制要求所有常用头文件必须在`stdafx.h`中显式包含[^1] 2. **源文件包含顺序错误** `#include "stdafx.h"` 必须是源文件中的第一个包含指令 --- ### 解决方案 #### 方法1:将`math.h`添加到预编译头文件(推荐) ```cpp // stdafx.h 或 pch.h #pragma once // 添加以下包含指令 #include <math.h> // 解决跳过警告[^2] // 其他标准库头文件 #include <windows.h> #include <stdlib.h> ... ``` #### 方法2:调整源文件包含顺序 ```cpp // 正确顺序:stdafx.h 必须是第一个包含指令 #include "stdafx.h" // 预编译头必须首位 // 然后包含其他头文件 #include <math.h> #include "my_header.h" int main() { double x = sin(M_PI/4); // 现在可正常使用 ... } ``` #### 方法3:禁用预编译头(不推荐) 1. 项目属性 → C/C++ → 预编译头 2. 设置 **预编译头** 为 **不使用预编译头** > 注意:这会显著增加编译时间[^2] --- ### 配置验证步骤 1. **检查包含目录** 项目属性 → C/C++ → 常规 → 附加包含目录 确保包含`$(WindowsSdkDir)`标准库路径 2. **重建预编译头** - 清理解决方案 - 重新生成`stdafx.cpp`(预编译头源文件) - 重新生成整个解决方案 3. **验证头文件包含** 在`stdafx.h`中添加: ```cpp #ifndef _MATH_H #error "math.h not included in precompiled header" #endif ``` --- ### 关键原理说明 | 配置项 | 正确值 | 错误配置后果 | |--------|--------|--------------| | 预编译头包含 | `#include <math.h>` | 跳过数学函数声明 | | 源文件包含顺序 | `stdafx.h`首位 | 预编译失效 | | 预编译头设置 | 创建(/Yc) | 未创建导致重复编译 | | 附加包含目录 | 包含SDK路径 | 找不到系统头文件 | > **最佳实践**:在`stdafx.h`中集中包含所有稳定库头文件(如STL、Windows API、数学库),可提升编译速度30%-50%[^1]。 --- ### 完整示例配置 **stdafx.h** ```cpp #pragma once #define _USE_MATH_DEFINES // 启用M_PI等常量 // 核心系统头文件 #include <windows.h> #include <math.h> // 数学函数 #include <cmath> // C++数学库(C++项目) #include <algorithm> // STL算法 ``` **main.cpp** ```cpp #include "stdafx.h" // 必须首位 int main() { double angle = M_PI / 4.0; // 正确使用数学常量 double result = sin(angle); // 正常调用函数 printf("sin(π/4) = %.3f\n", result); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值