C编译预处理宏
来源:互联网 发布:祝利荣牛熊线指标源码 编辑:程序博客网 时间:2024/05/16 18:30
一、编译预处理
作用:对源程序编译之前做一些处理,生成扩展C源程序
种类
宏定义 #define #ifdef #ifndef
文件包含 #include
条件编译 #if--#else--#endif等
其他宏定义 #line #error #pragma
格式: “#”开头
占单独一行
句末不用加分号
1-2 宏定义
无参数宏定义
有参数宏定义
#undef
不带参数宏定义
一般形式: #define 宏名 [宏体]
功能:用指定标识符(宏名)代替字符序列(宏体)
如 #define YES 1
#define NO 0
#define PI 3.1415926
#define OUT printf(“Hello,World”);
如 if(x==YES) printf(“correct!\n”);
else if (x==NO) printf(“error!\n”);
展开后: if(x==1) printf(“correct!\n”);
else if (x==0) printf(“error!\n”);
例 #define WIDTH 80
#define LENGTH WIDTH+40
var=LENGTH*2;
宏展开:var= 80+40 *2;
宏定义的规则
宏名一般习惯用大写字母表示,以便与变量名相区别
宏定义不是C语句,不必在行末加分号
在进行宏定义时,可以引用已定义的宏名,可以层层替换。
只作字符替换,不分配内存空间。
宏定义的特点
宏名一般习惯用大写字母表示
提高程序的通用性
宏名的有效范围为定义命令之后到本源文件结束
可以用#undef命令终止宏定义的作用域
宏定义只作简单的替换,不作正确性检查
1-2-2 带参数宏定义
一般形式: #define 宏名(参数表) 宏体
例 #define S(a,b) a*b
………..
area=S(3,2);
宏展开: area=3*2;
带参宏规则
形参用实参换,其它字符保留;
宏名与参数列表之间不能有空格;
宏体及各形参之间应加空格;
注意宏体的括号;
例 #define POWER(x) x*x
x=4; y=6;
z=POWER(x+y);
宏展开:z=x+y*x+y;
一般写成: #define POWER(x) ((x)*(x))
宏展开: z=((x+y)*(x+y));
带参数宏定义的特点
带参宏定义中,宏名和形参表之间不能有空格出现
例如: #define MAX(a,b) (a>b)?a:b
写为: #define MAX (a,b) (a>b)?a:b
将被认为是无参宏定义,宏名MAX代表字符串 (a,b)(a>b)?a:b
在带参宏定义中,形式参数不分配内存单元,因此不必作类型定义
在宏定义中的形参是标识符,而宏调用中的实参可以是表达式
#define SQ(y) (y)*(y)
main()
{
int a,sq;
printf("input a number: ");
scanf("%d",&a);
sq=SQ(a+1);
printf("sq=%d\n",sq);
}
带参的宏和带参函数很相似,但有本质上的不同
#undef定义指令删除前面定义的宏名字。
表达一般形式为:
#undef macro-name
例子
#define MICRO 1
#undef MICRO
1-3 文件包含
功能:一个源文件可将另一个源文件的内容全部包含进来
一般形式: #include “文件名”
或 #include <文件名>
处理过程:预编译时,用被包含文件的内容取代该预处理命令,再对“包含”后的文件作一个源文件编译
文件包含可嵌套
/* powers.h */
#define sqr(x) ((x)*(x))
#define cube(x) ((x)*(x)*(x))
#define quad(x) ((x)*(x)*(x)*(x))
#include <stdio.h>
#include "powers.h"
#define MAX_POWER 10
void main()
{ int n;
printf("number\t exp2\t exp3\t exp4\n");
printf("----\t----\t-----\t------\n");
for(n=1;n<=MAX_POWER;n++)
printf("%2d\t %3d\t %4d\t %5d\n",n,sqr(n),cube(n),quad(n));
}
文件包含特点
一个include命令只能指定一个被包含文件
可以用双引号括起来,也可以用尖括号括起来。
文件包含允许嵌套
被包含文件(file2.h)与其所在的文件(file.c)在预编译之后已成为同一个文件
1-4 条件编译
#if、#else、#elif #endif
#ifdef和#ifndef
条件编译指令中最常用的或许是#if,#else,#elif和#endif
#if的一般形式是:
#if constant-expression
Statement sequence
#endif
#endif标记#if块的结束
例子:
#ifdef COMPUTER_A
#define INTEGER_SIZE 16
#else
# define INTEGER_SIZE 32
#endif
#else指令的作用与C语言的else相似,#if指令失败时它可以作为备选指令
#else既是标记#if块的结束,也标记#else块的开始
每个#if只能写一个#endif匹配
#elif指令的意思是“否则,如果”
语法格式:
#if expression
Statement sequence
#elif expression1
Statement sequence
#elif expression2
。。。。。。
#elif expression
Statement sequence
#endif
#ifdef --如果已定义
#ifdef的一般形式如下:
#ifdef 标识符
程序段1
#else
程序段2
#endif
当所指定的标识符已经被#define命令定义过,则在程序编译阶段只编译程序段1,否则编译程序段2。
#ifdef和#ifndef
#inlucde <stdio.h>
#define T 10
int main(void)
{
#ifdef t
Printf(“Hi T\n”);
#else
Printf(“Hi anyone\n”);
#endif
#ifndef M
Printf(“M Not Defined\n”);
#endif
return 0;
}
操作符#通常称为字符串化的操作符
#include <stdio.h>
#define mkstr(s) #s
int main(void)
{
Printf(mkstr(I like C));
Return 0;
}
预处理程序把以下的语句:
Printf(mkstr(I like C));
变成
Printf(“I like C”);
##”可以把两个独立的字符串连接成一个字符串
#define CONNECT(X, Y) X##Y
void cout1(){printf("mode 1\n");}
void cout2(){printf("mode 2\n");}
void cout3(){printf("mode 3\n");}
int main()
{
CONNECT(cout, 3)();
}
1-5-6 预定义宏
__DATE__ 进行预处理的日期(“Mmm dd yyyy”形式的字符串文字)
__FILE__ 代表当前源代码文件名的字符串文字
__LINE__ 代表当前源代码中的行号的整数常量
__TIME__ 源文件编译时间,格式微“hh:mm:ss”
__func__ 当前所在函数名
例子
#include <stdio.h>
#include <stdlib.h>
void why_me();
int main()
{
printf( "The file is %s.\n", __FILE__ );
printf( "The date is %s.\n", __DATE__ );
printf( "The time is %s.\n", __TIME__ );
printf( "This is line %d.\n", __LINE__ );
printf( "This function is %s.\n", __func__ );
why_me();
return 0;
}
void why_me()
{
printf( "This function is %s\n", __func__ );
printf( "The file is %s.\n", __FILE__ );
printf( "This is line %d.\n", __LINE__ );
}
- C编译预处理宏
- c++/c编译预处理
- C 预处理指令 宏定义 条件编译
- 【C语言】编译预处理及宏定义
- C / C++ 编译预处理
- C语言编译预处理
- c编译预处理
- c/c++编译预处理
- C预处理及编译
- 【C语言】编译预处理
- C语言编译预处理
- C/C++编译预处理
- c/c++编译预处理
- C语言编译预处理
- C语言编译预处理
- C/C++编译预处理指令
- C&C++编译预处理大全
- C语言中的编译预处理
- SSH整合报错:failed to lazily initialize a collection of role
- android-swipelistview使用说明
- Android中meta-data的使用
- HDU 4539 【状压DP】
- TestLink 与 Mantis的集成
- C编译预处理宏
- MYSQL的WHERE子句
- Redis命令
- iOS-浅谈runtime运行时机制01-类与对象的内部结构
- Windows内核编程基础篇之系统线程
- 九度OJ-题目1001:A+B for Matrices
- iOS XML解析
- iOS高效编程秘诀—坚持编程习惯
- 应用内存优化之OnLowMemory&OnTrimMemory