- 浏览: 138183 次
- 性别:
- 来自: 杭州
最新评论
-
ziyuetian1943:
刚开始接触DB2 存储过程,在楼主这儿学习了
DB2存储过程总结 -
liubey:
我想问这个存储过程需要编译一下吗,也就是先执行一下,还是直接放 ...
在JAVA中调用DB2存储过程 -
新入职:
咦?竟然在2个月前留过言!
jQuery:基本教程 -
incredible:
good !
java中final与static关键字 -
jiangnan9399:
我现在正在学习JQery看了你的教程帮助很大,谢谢啦,
jQuery:基本教程
C预处理器是一种简单的宏处理器。
预处理器是由特殊的预处理器命令行控制的,它们是以#符号开头的源文件行。
预处理器的一般操作:从源文件中删除所有的预处理器命令行,并在源文件中执行这些预处理器命令所指定的转换操作
预处理器代码行的语法与C语言其他部分的语法是完全独立的,但经过预处理所产生的源代码必须在上下文环境中合法
常见的预处理器命令:
#define 定义一个预处理器宏
#undef 取消一个预处理器宏
#include 插入另一个源文件的文本
#if 测试一个常量表达式的值
#ifdef 测试如果一个宏已被定义
#ifndef 测试如果一个宏没有被定义
#else 测试失败后
#endif 终止条件文本
#line 提供用于编译器信息的行号
#elif 与else if相似
defined 判断一个宏是否被定义,已定义返回1,否则返回0,其与#if和#elif联用
# 将#后的宏标记转化为字符串
## 将两个相邻的宏标记连接成一个整体标记
#pragma 指定依赖编译器的信息
#error 用指定的信息产生一个编译时错误
1.预处理器词法约定
·以#开始的行被看成是预处理器命令
·命令的名称必须紧随#字符之后(标准C编译器允许#后出现空格,而一些旧式编译器不允许)
·如果只有一个#,则被看null指令,当成空行处理
·如果命令名称后不包含命令参数,则命令名称后必须是空白字符或注释,例:
#define PLUS + 或 #define PLUS /* */ +
·如果命令名称带参数,则左括号必须紧随命令名称
·如果一个宏被展开之后是一些看上去像预处理器命令,这些命令不会被标准C编译器所认识, 例:
#define GETMATH #include <math.h>
GETMATCH展开后为 # include < math . h>,会被编译为错误C代码
·在命令行末加\可以进行续行,例
#define err(flag,msg) if(flag) \
printf(msg)
2.宏的定义
·语法:
·Object-liked defined
#define 宏名 标记序列
·With parameter list defined
#define 宏名(parameter list) 标记序列
3.宏扫描
·规则:当一个宏被展开之后,对宏调用的扫描就在宏展开的开始位置继续,使宏名称在被展开宏的内部可以被认识,以便进一步的宏替换,例
#define plus(x,y) add(y,x)
#define add(x,y) ((x)+(y))
对plus(plus(a,b),c)进行宏展开,步骤如下:
plus(plus(a,b),c)
=>add(c,plus(a,b))
=>((c)+(plus(a,b)))
=>((c)+(add(b,a)))
=>((c)+((b)+(a)))
·自身宏嵌套
·在标准C中,出现在自身的展开体中的宏并不会被重新展开
·旧式的C预处理器在传统中并不会检测这种递归,而是试图继续展开直到系统出错为止
4.预定义的宏
·常用的预定义的宏有:
__LINE__ 当前源程序行的行号,用十进制整数常量表示
__FILE__ 当前源文件的名称,用字符串常量表示
__DATE__ 编译时的日期,用“MM dd yyyy”形式的字符串常量表示
__TIME__ 编译时的时间,用“hh:mm:ss”形式的字符串常量表示
__STDC__ 当且只当编译器遵循ISO标准时,它的值是十进制常量1
__STDC__VERSION__ 如果编译器遵循C99,则这个宏的值是199901L,其他情况下,该宏没定义
__STDC__HOSTED__ 当前是宿主系统,该宏值为1,当前是独立系统,这个宏值为0
__STDC__IEC__559__ 如果浮点实现遵循IEC 60599标准,这个宏值为1,否则无定义
__STDC__IEC__559__COMPLEX__ 如果复数运算实现遵循IEC 60559标准,则该宏值为1,否则未定义
__STDC__ISO10646__ 定义为一个长整数常量
5.取消宏定义和宏的重定义
·使用#undef命令,语法:
#undef 宏名
·避免宏的重定义,使用#ifndef或#ifdef命令,例
#ifndef MYHEADER_H
#define MYHEADER_H 2000
#endif
6.宏展开的优先级错误
·宏的操作完全是标记的文本替换,只有在宏展开结束后,才会把宏体解析为声明,表达式或语句,例:
#define SQUARE(x) x*x
SQUARE(a)=>a*a //ok
SQUARE(a+b)=>a+b*a+b //???
·避免这种事件发生,可以使用括号
#define SQUARE(x) (x)*(x)
SQUARE(a+b)=>(a+b)*(a+b) //ok
7.把标记转换为字符串
·在标记序列中使用#,例
#define TEST(a,b) printf( #a "<" #b "=%d\n", (a)<(b) )
TEST(0,0xFFFF)=>printf("0<0xFFFF=%d\n", (0)<(0xFFFF))
8.宏展开中的标记合并
·在标中使用##,例
#define NAME(i) name ## i
NAME(1)=>name1
9.宏的可变参数列表
·使用省略号来表示宏参数中的可变参数列表,语法:
#define 宏名(参数列表,...) 标记序列
#define 宏名(...) 标记序列
·在标记序列中使用__VA__ARGS__来对应参数列表中的...,例
#define MAKE_EM_A_STRING(...) #__VA__ARGS__
MAKE_EM_A_STRING(a,b,c,d)=>"a,b,c,d"
10.文件包含
·使用#include命令,形式如下:
#include <字符序列>
#include "字符序列"
#include 标记序列
·使用<>和""的区别在于编译器查找包含文件的方式
<>:根据编译器的定义规则和路径进行查找
"":从源文件的当前路径开始查找,如果不存在,则以<>形式来处理
11.条件编译
·使用#if,#else,#endif命令,形式:
#if 常量表达式
....
#else
...
#endif
·使用#elif命令,形式
#if 常量表达式1
...
#elif 常量表达式2
...
#elif 常量达式n
...
#else
...
#endif
·使用#ifdef和#ifndef命令,形式
#ifdef 宏名
表示如果该宏名已被定义,则相当于#if 1
如果该宏名没有定义,则相当于#if 0
·defined操作符
·defined操作符可以在#if和#elif表达式中使用,不能用于别处,形式
defined name
defined (name)
例:
#if defined(VAX) 代替
#ifdef VAX
12.显示的行号
·使用#line命令,形式:
#line n "filename"
#line n
表示源代码的下一行来自用户所编写的filename的文件的第n行,n必须是十进制数字
13.pragma指定
·以添加新的预处理器功能或者向编译器提供因实现而异的信息
·标准pragma命令
#pragma [FP_CONTRACT|FENV_ACCESS|CX_LIMITED_RANGE] [ON|OFF|DEFAULT]
·_Pragma操作符,形式:
_Pragma("字符串序列")
例:
_Pragma("STDC FENV_ACCESS ON") 等价于
#pragma STDC FENV_ACCESS ON
14.错误指令
·使用#error命令,形式
#error 预处理器标记
·如果信息中包含有宏,而不想将宏进行展开,可以使用字符串形式
#define SIZE 1024
#if (SIZE%256 !=0 )
#error "SIZE must be a multiple of 256"
#endif
15.关于一些旧编译器空白字符的预处理
例:
#define INC ++
#define TAB internal_table
#define INCTAB table_of _increments
#define CONC(x,y) x/**/y
对于CONC(INC,TAB)进行展开,标准与非标准编译器处理方式:
标准 非标准
CONC(INC,TAB) CONC(INC,TAB)
INC TAB INCTAB 这里出现了不一样的结果
++ internal_table table_of_increments 导致结果也不一样了
预处理器是由特殊的预处理器命令行控制的,它们是以#符号开头的源文件行。
预处理器的一般操作:从源文件中删除所有的预处理器命令行,并在源文件中执行这些预处理器命令所指定的转换操作
预处理器代码行的语法与C语言其他部分的语法是完全独立的,但经过预处理所产生的源代码必须在上下文环境中合法
常见的预处理器命令:
#define 定义一个预处理器宏
#undef 取消一个预处理器宏
#include 插入另一个源文件的文本
#if 测试一个常量表达式的值
#ifdef 测试如果一个宏已被定义
#ifndef 测试如果一个宏没有被定义
#else 测试失败后
#endif 终止条件文本
#line 提供用于编译器信息的行号
#elif 与else if相似
defined 判断一个宏是否被定义,已定义返回1,否则返回0,其与#if和#elif联用
# 将#后的宏标记转化为字符串
## 将两个相邻的宏标记连接成一个整体标记
#pragma 指定依赖编译器的信息
#error 用指定的信息产生一个编译时错误
1.预处理器词法约定
·以#开始的行被看成是预处理器命令
·命令的名称必须紧随#字符之后(标准C编译器允许#后出现空格,而一些旧式编译器不允许)
·如果只有一个#,则被看null指令,当成空行处理
·如果命令名称后不包含命令参数,则命令名称后必须是空白字符或注释,例:
#define PLUS + 或 #define PLUS /* */ +
·如果命令名称带参数,则左括号必须紧随命令名称
·如果一个宏被展开之后是一些看上去像预处理器命令,这些命令不会被标准C编译器所认识, 例:
#define GETMATH #include <math.h>
GETMATCH展开后为 # include < math . h>,会被编译为错误C代码
·在命令行末加\可以进行续行,例
#define err(flag,msg) if(flag) \
printf(msg)
2.宏的定义
·语法:
·Object-liked defined
#define 宏名 标记序列
·With parameter list defined
#define 宏名(parameter list) 标记序列
3.宏扫描
·规则:当一个宏被展开之后,对宏调用的扫描就在宏展开的开始位置继续,使宏名称在被展开宏的内部可以被认识,以便进一步的宏替换,例
#define plus(x,y) add(y,x)
#define add(x,y) ((x)+(y))
对plus(plus(a,b),c)进行宏展开,步骤如下:
plus(plus(a,b),c)
=>add(c,plus(a,b))
=>((c)+(plus(a,b)))
=>((c)+(add(b,a)))
=>((c)+((b)+(a)))
·自身宏嵌套
·在标准C中,出现在自身的展开体中的宏并不会被重新展开
·旧式的C预处理器在传统中并不会检测这种递归,而是试图继续展开直到系统出错为止
4.预定义的宏
·常用的预定义的宏有:
__LINE__ 当前源程序行的行号,用十进制整数常量表示
__FILE__ 当前源文件的名称,用字符串常量表示
__DATE__ 编译时的日期,用“MM dd yyyy”形式的字符串常量表示
__TIME__ 编译时的时间,用“hh:mm:ss”形式的字符串常量表示
__STDC__ 当且只当编译器遵循ISO标准时,它的值是十进制常量1
__STDC__VERSION__ 如果编译器遵循C99,则这个宏的值是199901L,其他情况下,该宏没定义
__STDC__HOSTED__ 当前是宿主系统,该宏值为1,当前是独立系统,这个宏值为0
__STDC__IEC__559__ 如果浮点实现遵循IEC 60599标准,这个宏值为1,否则无定义
__STDC__IEC__559__COMPLEX__ 如果复数运算实现遵循IEC 60559标准,则该宏值为1,否则未定义
__STDC__ISO10646__ 定义为一个长整数常量
5.取消宏定义和宏的重定义
·使用#undef命令,语法:
#undef 宏名
·避免宏的重定义,使用#ifndef或#ifdef命令,例
#ifndef MYHEADER_H
#define MYHEADER_H 2000
#endif
6.宏展开的优先级错误
·宏的操作完全是标记的文本替换,只有在宏展开结束后,才会把宏体解析为声明,表达式或语句,例:
#define SQUARE(x) x*x
SQUARE(a)=>a*a //ok
SQUARE(a+b)=>a+b*a+b //???
·避免这种事件发生,可以使用括号
#define SQUARE(x) (x)*(x)
SQUARE(a+b)=>(a+b)*(a+b) //ok
7.把标记转换为字符串
·在标记序列中使用#,例
#define TEST(a,b) printf( #a "<" #b "=%d\n", (a)<(b) )
TEST(0,0xFFFF)=>printf("0<0xFFFF=%d\n", (0)<(0xFFFF))
8.宏展开中的标记合并
·在标中使用##,例
#define NAME(i) name ## i
NAME(1)=>name1
9.宏的可变参数列表
·使用省略号来表示宏参数中的可变参数列表,语法:
#define 宏名(参数列表,...) 标记序列
#define 宏名(...) 标记序列
·在标记序列中使用__VA__ARGS__来对应参数列表中的...,例
#define MAKE_EM_A_STRING(...) #__VA__ARGS__
MAKE_EM_A_STRING(a,b,c,d)=>"a,b,c,d"
10.文件包含
·使用#include命令,形式如下:
#include <字符序列>
#include "字符序列"
#include 标记序列
·使用<>和""的区别在于编译器查找包含文件的方式
<>:根据编译器的定义规则和路径进行查找
"":从源文件的当前路径开始查找,如果不存在,则以<>形式来处理
11.条件编译
·使用#if,#else,#endif命令,形式:
#if 常量表达式
....
#else
...
#endif
·使用#elif命令,形式
#if 常量表达式1
...
#elif 常量表达式2
...
#elif 常量达式n
...
#else
...
#endif
·使用#ifdef和#ifndef命令,形式
#ifdef 宏名
表示如果该宏名已被定义,则相当于#if 1
如果该宏名没有定义,则相当于#if 0
·defined操作符
·defined操作符可以在#if和#elif表达式中使用,不能用于别处,形式
defined name
defined (name)
例:
#if defined(VAX) 代替
#ifdef VAX
12.显示的行号
·使用#line命令,形式:
#line n "filename"
#line n
表示源代码的下一行来自用户所编写的filename的文件的第n行,n必须是十进制数字
13.pragma指定
·以添加新的预处理器功能或者向编译器提供因实现而异的信息
·标准pragma命令
#pragma [FP_CONTRACT|FENV_ACCESS|CX_LIMITED_RANGE] [ON|OFF|DEFAULT]
·_Pragma操作符,形式:
_Pragma("字符串序列")
例:
_Pragma("STDC FENV_ACCESS ON") 等价于
#pragma STDC FENV_ACCESS ON
14.错误指令
·使用#error命令,形式
#error 预处理器标记
·如果信息中包含有宏,而不想将宏进行展开,可以使用字符串形式
#define SIZE 1024
#if (SIZE%256 !=0 )
#error "SIZE must be a multiple of 256"
#endif
15.关于一些旧编译器空白字符的预处理
例:
#define INC ++
#define TAB internal_table
#define INCTAB table_of _increments
#define CONC(x,y) x/**/y
对于CONC(INC,TAB)进行展开,标准与非标准编译器处理方式:
标准 非标准
CONC(INC,TAB) CONC(INC,TAB)
INC TAB INCTAB 这里出现了不一样的结果
++ internal_table table_of_increments 导致结果也不一样了
发表评论
-
Struts2 namespace总结
2010-03-08 20:50 1738创建struts2的应用,首先 ... -
The Zen of Python
2009-12-26 23:46 878Abstract Long time Pythone ... -
权限控制
2009-10-28 09:23 815在系统权限控制中,要考虑资源功能是属于人,还是属于职位。观察这 ... -
javascript常用tools
2009-10-15 15:46 860//函数说明:求第y年第m月的天数 // ... -
javascript中 null 与 undefined的区别
2009-10-10 21:59 2622第一篇 解剖JavaScript中的null和undefine ... -
jQuery:基本教程
2009-09-30 15:24 1284jQuery:基本教程 这个教程是帮助初始学习jQuer ... -
javascript中获取浏览器的url
2009-09-03 18:47 1713document.location location.hre ... -
java中final与static关键字
2009-08-08 11:21 1467一.final总结 1.final修饰 ... -
linux下ssh安全配置
2009-07-09 13:25 3156linux下ssh安全配置 ssh配置文件目录: /etc ... -
python 学习笔记(一)
2009-05-17 10:40 928(一)软件的安装与配置 1.Python安装(Windows ... -
Mysql数据库导入导出
2009-05-15 16:25 16021. 概述MySQL数据库的导入,有两种方法:1) 先导出数据 ... -
Apache Commons Digester 的使用
2009-05-06 20:41 1257Learning and Using Jakarta Dige ... -
rpm软件管理
2009-04-30 20:26 1369RPM套件安裝 一、基本安裝 rpm -ivh 軟體套件 ... -
linux系统启动详解
2009-04-28 19:28 1269本文以RedHat9.0和i386平台 ... -
解读<c:out>源码
2009-04-23 17:43 3427<c:out>标签是用来在页面中输出属性值,在使用 ... -
使用 MERGE 语句更新表和视图内容
2009-04-20 12:37 1933DB2® 数据库管理器能够使用来自另一个源的数据(通常是表引用 ... -
高质量JAVA:错误模式
2009-04-08 11:43 798错误模式:介绍 诊断和纠正 Java 程序中反复出现 ... -
电器销售需求分析
2009-04-05 15:52 1033电器销售需求分析 doc 基本完成 基本 ... -
汇编编程推荐书目
2009-04-05 15:01 1401书名:《Windows环境 ... -
w3school帮助文档
2009-04-05 14:35 1289w3school帮助文档 中文版 chm
相关推荐
c preprocessor c preprocessor
这份文件是关于C语言预处理器的详细介绍,包括其工作原理、主要功能、GCC编译过程中预处理器的角色以及预处理指令的使用和规则。以下是文件的核心内容概要: 1. **预处理器工作原理**: 2. **GCC编译过程及常用选项*...
C语言预处理器 C 预处理器不是编译器的组成部分,但是它是编译过程中一个单独的步骤。简言之,C 预处理器只不过是一个文本替换工具而已,它们会指示编译器在实际编译之前完成所需的预处理。我们将把 C 预处理器(C ...
尽管有些C程序员十分依赖于预处理器,我依然建议适度地使用它,就像许多其他生活中的事物一样。现代的C语言编程风格呼吁减少对于处理器的依赖。在C++中,对语言的改变使得可以更进一步限制预处理器的使用。 <br>
如果你要做编译原理的作业,要做预处理,此乃神器
本资料描述了C++预处理器做了那些工作,以及如何做的。特别是一些编程的注意事项,对于编程也有提高!
很棒的C预处理器 很棒的C预处理器清单 专案 一种用于C99预处理程序元编程的功能语言。 具有求和类型的C99 -C宏预处理器上的编译时LISP解释器。 预处理模块 vmd-Boost.org VMD模块 -order-pp预处理程序库(chaos...
C 预处理器不是编译器的组成部分,是编译过程中一个单独的步骤。C预处理器只是一个文本替换工具,它会指示编译器在实际编译之前完成所需的预处理。 所有的预处理器命令都是以井号(#)开头。它必须是第一个非空字符...
C预处理器实用程序 介绍 zen.h是C预处理程序宏的集合。 目前,它仅提供了一个小型框架,仅用于通过C预处理器管理32位计数器,但将来可能会扩展。 除了内置的(和非标准的) __COUNTER__之外,为C预处理器实现新颖的...
直流电源用于高科技C编译器v3.09的新C预处理器介绍当我从Hi-Tech C编译器软件包v3.09开始反编译预处理器时,我发现错误消息与John F. Reiser {John F. Reiser}编写的程序消息完全相同。 因此,我假设Hi-Tech C预处理...
但是,如果您是从 C 编程背景开始使用 MATLAB,您可能想知道 MATLAB 的预处理器在哪里。 好吧,MATLAB 没有自带。MPP 旨在填补这一空白。 的确,您可以在 MATLAB 代码上使用您最喜欢的 C 预处理器,但有几个原因会...
应用程序用 Java 编写的类似 C 的预处理器,具有 C 预处理器之外的功能
一个更强大的C / C 预处理器
这个纯粹的Lua模块实现(1)具有几个有用扩展的标准兼容C预处理器,以及(2)解析器,该解析器在C头文件或C程序文件中提供所有全局声明和定义的Lua友好描述。 驱动程序lcpp调用预处理器并输出预处理的代码。 尽管...
就在被带到编译器那里之前,预处理器都会对你的源代码瞧上一瞧, 做一些格式化的工作,并执行任何你在源代码里面留给它来执行的指令. 像什么? 好吧,预处理器的指令就被叫做预处理器指令,而他们都以一个#开头. 像 #...
该项目包含仅在C预处理器宏中编写的Brainfuck程序解释器。 如何使用 产生标题 $ make 将您的程序编码到main.h ,并提供用作输入的文件 $ ./bf_to_main.sh hello.bf /dev/null > main.h 运行大脑他妈的解释器 $ make ...
DECUS C 语言源程序预处理器
然后详细讲解了预处理器和宏的相关知识,如宏定义、条件编译、头文件引用等,也给出了示例代码进行解释说明。最后提供了文件操作和宏的综合应用示例。内容结构清晰,知识点突出。 适合人群: 学习C语言的学生或者初级...
它是一个通过 c 预处理器管道源代码的钩子(由 )。 但为什么? 不言而喻,这是一个糟糕的想法,但这并不意味着只要我记得,我就一直渴望在 javascript 中拥有一种熟悉的感觉宏系统。 如何? 读出的和,和/或。 ...