From: http://www.neu.edu.cn/cxsj/pointchart/c11/index.html
  
#pragma指令
TAG: 预编译和宏定义,ANSI C,# pragma
TEXT:
其语法格式如下:
# pragma token-sequence
此指令的作用是触发所定义的动作。如果token- sequence存在,则触发相应的动作,否则忽略。此指令一般为编译系统所使用。例如在Visual C++.Net 中利用# pragma once 防止同一代码被包含多次。
#line指令
 TAG: 预编译和宏定义,ANSI C,#line
TEXT:
此命令主要是为强制编译器按指定的行号,开始对源程序的代码重新编号,在调试的时候,可以按此规定输出错误代码的准确位置。
形式1
语法格式如下:
# line constant “filename”
其作用是使得其后的源代码从指定的行号constant重新开始编号,并将当前文件的名命名为filename。例如下面的程序如下:
#include "stdio.h"
void Test();
#line 10 "Hello.c"
int main(int argc, char* argv[])
{
#define CONST_NAME1 "CONST_NAME1"
printf("%s\n",CONST_NAME1);
#undef CONST_NAME1
printf("%s\n",CONST_NAME1);
{
#define CONST_NAME2 "CONST_NAME2"
printf("%s\n",CONST_NAME2);
}
printf("%s\n",CONST_NAME2);
return 0;
}
void Test()
{
printf("%s\n",CONST_NAME2);
}
提示如下的编译信息:
Hello.c(15) : error C2065: 'CONST_NAME1' : undeclared identifier
表示当前文件的名称被认为是Hello.c, #line 10 "Hello.c"所在的行被认为是第10行,因此提示第15行出错。
形式2
语法格式如下:
# line constant
其作用在于编译的时候,准确输出出错代码所在的位置(行号),而在源程序中并不出现行号,从而方便程序员准确定位。
#undef指令
TAG: 预编译和宏定义,ANSI C,取消符号常量定义命令
TEXT:
取消符号常量定义命令,语法形式如下:
#undef 符号常量名称(或编译标志)
其作用取消最近一次#define符号常量名称(或编译标志)命令,使定义的符号常量或编译标志失效。
例11-3 分析如下的代码
#include "stdio.h"
void Test();
int main(int argc, char* argv[])
{
#define CONST_NAME1 "CONST_NAME1"
printf("%s\n",CONST_NAME1);
#undef CONST_NAME1
printf("%s\n",CONST_NAME1); /* 错误,CONST_NAME1的定义已经取消*/
{
#define CONST_NAME2 "CONST_NAME2"
printf("%s\n",CONST_NAME2);
}
printf("%s\n",CONST_NAME2);
return 0;
}
void Test()
{
printf("%s\n",CONST_NAME2);
}
在程序的编译的时候,系统提示如下信息
error C2065: 'CONST_NAME1' : undeclared identifier
出现上述编译错误的原因是,在第二次应用符号常量CONST_NAME1时,此符号常量已经被取消定义。
符号常量的有效范围是从第一次出现的位置开始,到#undef结束。如果没有对应的#undef指令,则到文件末尾结束。因此在本例中void Test函数可以直接使用CONST_NAME2,而无须定义。
提示 符号常量与变量的有效范围不同。变量根据其所在位置,例如某函数或文件决定其有效性,在函数内部定义的变量不能够为其他的函数所使用。但是符号常量仅仅与其出现先后位置,以及对应的#undef命令相关,与是否出现在具体函数无关。
  
  
运算符#和##
TAG: 预编译和宏定义,运算符#和##
TEXT:
在ANSI C中为预编译指令定义了两个运算符——#和##。
# 的作用是实现文本替换,例如
#define HI(x) printf("Hi,"#x"\n");
void main()
{
HI(John);
}
程序的运行结果
Hi,John
在预编译处理的时候, "#x"的作用是将x替换为所代表的字符序列。在本程序中x为John,所以构建新串“Hi,John”。
##的作用是串连接。
例如
#define CONNECT(x,y) x##y
void main()
{
int a1,a2,a3;
CONNECT(a,1)=0;
CONNECT(a,2)=12;
a3=4;
printf("a1=%d\ta2=%d\ta3=%d",a1,a2,a3);
}
程序的运行结果为
a1=0 a2=12 a3=4
在编译之前, CONNECT(a,1)被翻译为a1, CONNECT(a,2)被翻译为a2。

 

VC++

预编译头文件说明

VC++的预编译功能
TAG: 预编译和宏定义,VC++,VC++的预编译功能
TEXT:
这里介绍VC6的预编译功能的使用,由于预编译详细使用比较的复杂,这里只介绍几个最重要的预编译指令: /Yu, /Yc,/Yx,/Fp。其它的详细资料可以参考: MSDN -> Visual Studio 6.0 Document -> Visual C++ 6.0 Document -> VC++ Programmer Guider - >Compiler and Linker -> Details -> Creating Precompiled Header files
预编译头的概念:
所谓的预编译头就是把一个工程中的那一部分代码,预先编译好放在一个文件里(通常是以.pch为扩展名的),这个文件就称为预编译头文件这些预先编译好的代码可以是任何的C/C++代码,甚至是inline的函数,但是必须是稳定的,在工程开发的过程中不会被经常改变。如果这些代码被修改,则需要重新编译生成预编译头文件。注意生成预编译头文件是很耗时间的。同时你得注意预编译头文件通常很大,通常有6- 7M大。注意及时清理那些没有用的预编译头文件。
也许你会问:现在的编译器都有Time stamp的功能,编译器在编译整个工程的时候,它只会编译那些经过修改的文件,而不会去编译那些从上次编译过,到现在没有被修改过的文件。那么为什么还要预编译头文件呢?答案在这里,我们知道编译器是以文件为单位编译的,一个文件经过修改后,会重新编译整个文件,当然在这个文件里包含的所有头文件中的东西(.eg Macro, Preprocessor )都要重新处理一遍。 VC的预编译头文件保存的正是这部分信息。以避免每次都要重新处理这些头文件。
根据上文介绍,预编译头文件的作用当然就是提高便宜速度了,有了它你没有必要每次都编译那些不需要经常改变的代码。编译性能当然就提高了。
要使用预编译头,我们必须指定一个头文件,这个头文件包含我们不会经常改变的代码和其他的头文件,然后我们用这个头文件来生成一个预编译头文件(.pch文件)想必大家都知道 StdAfx.h这个文件。很多人都认为这是VC提供的一个“系统级别”的,编译器带的一个头文件。其实不是的,这个文件可以是任何名字的。我们来考察一个典型的由AppWizard生成的MFC Dialog Based 程序的预编译头文件。(因为AppWizard会为我们指定好如何使用预编译头文件,默认的是StdAfx.h,这是VC起的名字)。我们会发现这个头文件里包含了以下的头文件:
#include <afxwin.h> // MFC core and standard components
#include <afxext.h> // MFC extensions
#include <afxdisp.h> // MFC Automation classes
#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls
#include <afxcmn.h>
这些正是使用MFC的必须包含的头文件,当然我们不太可能在我们的工程中修改这些头文件的,所以说他们是稳定的。
那么我们如何指定它来生成预编译头文件。我们知道一个头文件是不能编译的。所以我们还需要一个cpp文件来生成.pch 文件。这个文件默认的就是StdAfx.cpp。在这个文件里只有一句代码就是:#include“Stdafx.h”。原因是理所当然的,我们仅仅是要它能够编译而已―――也就是说,要的只是它的.cpp的扩展名。我们可以用/Yc编译开关来指定StdAfx.cpp来生成一个.pch文件,通过/Fp编译开关来指定生成的pch文件的名字。打开project - >Setting->C/C++ 对话框。把Category指向Precompiled Header。在左边的树形视图里选择整个工程,Project Options(右下角的那个白的地方)可以看到 /Fp “debug/PCH.pch”,这就是指定生成的.pch文件的名字,默认的通常是 <工程名>.pch。然后,在左边的树形视图里选择StdAfx.cpp,这时原来的Project Option变成了 Source File Option(原来是工程,现在是一个文件,当然变了)。在这里我们可以看到 /Yc开关,/Yc的作用就是指定这个文件来创建一个Pch文件。/Yc后面的文件名是那个包含了稳定代码的头文件,一个工程里只能有一个文件的可以有YC开关。VC就根据这个选项把 StdAfx.cpp编译成一个Obj文件和一个PCH文件。
这样,我们就设置好了预编译头文件。也就是说,我们可以使用预编译头功能了。以下是注意事项:
1)如果使用了/Yu,就是说使用了预编译,我们在每个.cpp文件的最开头,包含你指定产生pch文件的.h文件(默认是stdafx.h)不然就会有问题。如果你没有包含这个文件,就告诉你Unexpected file end.
2)如果你把pch文件不小心丢了,根据以上的分析,你只要让编译器生成一个pch文件就可以了。也就是说把 stdafx.cpp(即指定/Yc的那个cpp文件)重新编译一遍就可以了。

TAG: 预编译和宏定义,VC++,预编译头文件说明
TEXT:
所谓头文件预编译,就是把一个工程(Project)中使用的一些MFC标准头文件(如Windows.H、 Afxwin.H)预先编译,以后该工程编译时,不再编译这部分头文件,仅仅使用预编译的结果。这样可以加快编译速度,节省时间。
预编译头文件通过编译stdafx.cpp生成,以工程名命名,由于预编译的头文件的后缀是“pch”,所以编译结果文件是projectname.pch。
编译器通过一个头文件stdafx.h来使用预编译头文件。stdafx.h这个头文件名是可以在project的编译设置里指定的。编译器认为,所有在指令#include "stdafx.h"前的代码都是预编译的,它跳过#include "stdafx. h"指令,使用projectname.pch编译这条指令之后的所有代码。
因此,所有的CPP实现文件第一条语句都是:#include "stdafx.h"。
另外,每一个实现文件CPP都包含了如下语句:
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
这是表示,如果生成调试版本,要指示当前文件的名称。__FILE__是一个宏,在编译器编译过程中给它赋值为当前正在编译的文件名称。
VC默认情况下使用预编译头(/Yu),不明白的在加入新.h文件后编译时总出现fatal errorC1010: 在查找预编译头指令时遇到意外的文件结尾的错误。解决方法是在include头文件的地方加上#include"stdafx.h",或者打项目属性,找到“C/C++”文件夹,单击“预编译头”属性页。修改“创建/使用预编译头”属性为“不使用预编译头”。

转载于:https://my.oschina.net/alphajay/blog/3972

关于预编译和宏定义部分说明相关推荐

  1. Unity3D 多平台_预编译相关宏定义

    http://www.cnblogs.com/zhaoqingqing/p/3510332.html API地址:http://docs.unity3d.com/Documentation/Manua ...

  2. Android CMake 编译传递宏定义参数

    在做 C++ 需求开发时经常会遇到用宏定义来区分不同版本.不同平台的功能,如下所示: #ifdef DEBUG// 调用 debug 版本方法 #elif RELEASE// 调用 release 版 ...

  3. iOS_预编译(宏)#if #ifdef #ifndef #elif #else #endif

    iOS_预编译 1.预处理 ANSI C标准(是美国国家标准协会(ANSI)对C语言)规定可以在C源程序中加入一些"预处理命令",以改进程序设计环境,提高编译效率.这些预处理命令时 ...

  4. 关于VS中区分debug与release,32位与64位编译的宏定义

    在vs编程中,常常涉及到32位和64位程序的编译,怎么判断当前编译是32位编译还是64位编译?如何判断 是debug下编译还是release下编译?因为之前用到,这里记录一下,省的忘了又要疯狂的goo ...

  5. WebKit浏览器编译——开启宏定义

    例如:VIDEO 代码中已经对VIDEO做了一定的支持,但默认情况下并没有开启,这些支持都在一个ENABLE_VIDEO的宏定义中括起来了,可以grep下源代码看下有很多ENABLE(VIDEO)括起 ...

  6. MFC 不同编译平台宏定义

    Win32: WIN32 X64:_WIN64 Debug:_DEBUG Release: NDEBUG

  7. 【C 语言】编译过程 分析 ( 预处理 | 编译 | 汇编 | 链接 | 宏定义 | 条件编译 | 编译器指示字 )

    相关文章链接 : 1.[嵌入式开发]C语言 指针数组 多维数组 2.[嵌入式开发]C语言 命令行参数 函数指针 gdb调试 3.[嵌入式开发]C语言 结构体相关 的 函数 指针 数组 4.[嵌入式开发 ...

  8. c语言中条件编译相关的预编译指令

     一. 内容概述 本文主要介绍c语言中条件编译相关的预编译指令,包括#define.#undef.#ifdef.#ifndef.#if.#elif.#else.#endif.defined. 二. ...

  9. 【C语言】----宏定义,预处理宏

    什么是宏? 宏是学习任何语言所不可缺少的,优秀的宏定义可以使得代码变得很简洁且高效,有效地提高编程效率. 宏是一种预处理指令,它提供了一种机制,可以用来替换源代码中的字符串,解释器或编译器在遇到宏时会 ...

  10. c语言if多条件并列_C/C++编程笔记:C语言预编译指令—条件编译,零基础推荐收藏

    一. 内容概述 本文主要介绍c语言中条件编译相关的预编译指令,包括#define.#undef.#ifdef.#ifndef.#if.#elif.#else.#endif.defined. 二.条件编 ...

最新文章

  1. java配置文件报错_java使用spring框架配置文件时遇到的错误——Referenced file contains errors...
  2. 关于企业管理信息系统
  3. 程序员编程10大原则,请牢牢记住!
  4. Win10 C盘空间越来越小怎么办
  5. 实战经验:Oracle DG 的归档缺失修复
  6. meta 标签的详细使用
  7. 快速排序的递归方式和非递归方式
  8. python搭建django环境_在BAE上搭建python,django环境小记
  9. 三种找回丢失iPhone的方法,来自苹果手机找回网
  10. python数据分析的概念_Python数据分析入门篇
  11. UE4更改天空盒材质
  12. 零信任之从IAM概述到应用实现
  13. 读书笔记-架构整洁之道有感
  14. Linux下线程池概念详解以及代码演示
  15. 设计模式 模板模式和策略模式
  16. android studio引用高德地图api后地图显示白屏
  17. 用selenium来下载小姐姐图片并保存
  18. ES5ES6 day16
  19. Mysql体系构架详解——内存
  20. OpenVINO 环境配置

热门文章

  1. Thinkphp3.2+ 微信小程序图片上传
  2. 构建 Netflix 分布式追踪(tracing)体系
  3. java安装path_JDK安装时设置PATH和CLASSPATH环境变量有何作用?
  4. 快速理解浮动对标准流的影响
  5. gridreport php教程,谁能教我怎样才能把Grid++Report插件插入到.w页面中?
  6. JMeter接口测试入门
  7. Yii Framework2.0开发教程(5)数据库mysql函数
  8. 魔鬼定律:你一偷懒,必然出错,麒麟LINUX新版本无法安装
  9. 首发:成功解决MediaCodec中decoder超过720出错的问题
  10. link要使用全路径