在这里总结宏的使用方法欢迎补充1 条件include如下CODE#ifndef MAIN_H_#define MAIN_H_其它内容#endif上面在看到头文件时会看到作用就是阻止这个头文件被多次include多次include就会出现重复的定义情况所以需要在每个头文件中都使用这个定义如果还不是很了解要怎样使用可以看看c的标准头文件如fcntl.h2 条件编译如下CODE#ifdef _DEBUGprintf("this debug info\n");#endif如果没有定义_DEBUG宏的话那么上面那一行是不会编译进去的但是定义了_DEBUG后上面那行就会编译进去可以写个简单的程序测试CODE#include <stdio.h>int main(){#ifdef _DEBUGprintf("hello world\n");#elseprintf("no debug");#endifreturn 0;}第一次使用gcc -D_DEBUG main.c第二次使用gcc main.c运行两次的结果看3 定义为某个值以便后面修改这个值时不用修改其它地方代码只要修改这个宏的定义就可以了如一个软件的多语言版本等如下CODE#include <stdio.h>#define PRINT_STR "你好DD"main(){printf(PRINT_STR);return 0;}编译时会把PRINT_STR代替成"你好DD"以后想修改时就方便了另外也可以定义为函数#include <stdio.h>#ifdef _DEBUG#define A(x) a(x)#else#define A(x) b(x)#endifint a(int x){return x+1;}int b(int x){return x+100;}int main(){printf ("A(10) value is %d",A(10));return 0;}[/code]其实也可以定义成#define A a的但是定义成A(x)后只有A后面带一个(x)类型的编译器才会执行替换比较安全可以保证只替换函数而不替换变量第四个可变参数宏有些时候定义一个宏来代替某个函数但是这个函数是可变参数的话那就需要考虑办法了定义方法如下CODE#define PRINT(...) printf(__VA_ARGS__)#include <stdio.h>int main(){PRINT("%d %s %s",1,"吃饭了吗smile MM:)","\n");return 0;}第五个宏组合也就是## 和#的用法## 是连接符号连接两个宏#是把名字代替成字符串如下CODE#define s5(a) supper_ ## a#include <stdio.h>void supper_printf(const char* a){printf("this is supper printf:\n%s\n",a);}int main(){s5(printf)("hello owrld");return 0;}#用法如下#include <stdio.h>#define s(p) #pint main(){printf(s(p)"\n");return 0;}运行一下就知道了最后附上网上找到的宏定义的概念第一篇第九章预处理命令预处理的概念:编译之前的处理C的预处理主要有三个方面的内容:宏定义、文件包含、条件编译预处理命令以符号“#”开头。
9.1 宏定义9.1.1 不带参数的宏定义宏定义又称为宏代换、宏替换,简称“宏”格式:#define 标识符字符串其中的标识符就是所谓的符号常量,也称为“宏名”预处理(预编译)工作也叫做宏展开:将宏名替换为字符串。
掌握"宏"概念的关键是“换”。
一切以换为前提、做任何事情之前先要换,准确理解之前就要“换”。
即在对相关命令或语句的含义和功能作具体分析之前就要换,“不管三七二十一,先换了再说”。
那么剩下的问题就简单了:1 把谁换掉?2 换成什么?#define PI 3.1415926把程序中出现的PI全部换成3.1415926li9_1.c说明:(1)宏名一般用大写(2)使用宏可提高程序的通用性和易读性,减少不一致性,减少输入错误和便于修改。
例如:数组大小常用宏定义(3)预处理是在编译之前的处理,而编译工作的任务之一就是语法检查,预处理不做语法检查。
(4)宏定义末尾不加分号;(5)宏定义写在函数的花括号外边,作用域为其后的程序,通常在文件的最开头。
(6)可以用#undef命令终止宏定义的作用域(7)宏定义可以嵌套li9_2.c(8)字符串""中永远不包含宏(9)宏定义不分配内存,变量定义分配内存。
9.1.2 带参数的宏除了一般的字符串替换,还要做参数代换格式:#define 宏名(参数表)字符串例如:#define S(a,B) a*barea=S(3,2);第一步被换为area=a*b;,第二步被换为area=3*2;类似于函数调用,有一个哑实结合的过程li9_3.c(1)实参如果是表达式容易出问题#define S® r*rarea=S(a+B);第一步换为area=r*r;,第二步被换为area=a+b*a+b;正确的宏定义是#define S® ®*®(2)宏名和参数的括号间不能有空格(3)宏替换只作替换,不做计算,不做表达式求解(4)函数调用在编译后程序运行时进行,并且分配内存。
宏替换在编译前进行,不分配内存(5)宏的哑实结合不存在类型,也没有类型转换。
(6)函数只有一个返回值,利用宏则可以设法得到多个值li9_4.c(7)宏展开使源程序变长,函数调用不会(8)宏展开不占运行时间,只占编译时间,函数调用占运行时间(分配内存、保留现场、值传递、返回值)li9_5.c分析该例中的"9.2 “文件包含”处理一个文件包含另一个文件的内容格式:#include "文件名"或#include <文件名>编译时以包含处理以后的文件为编译单位,被包含的文件是源文件的一部分。
li9_6a.c li9_6b.c编译以后只得到一个目标文件.obj被包含的文件又被称为“标题文件”或“头部文件”、“头文件”,并且常用.h作扩展名。
修改头文件后所有包含该文件的文件都要重新编译头文件的内容除了函数原型和宏定义外,还可以有结构体定义,全局变量定义(1)一个#include命令指定一个头文件(2)文件1包含文件2,文件2用到文件3,则文件3的包含命令#include应放在文件1的头部第一行。
(3)包含可以嵌套(4)<文件名>称为标准方式,系统到头文件目录查找文件"文件名"则先在当前目录查找,而后到头文件目录查找(5)被包含文件中的静态全局变量不用在包含文件中声明。
9.3 条件编译有些语句行希望在条件满足时才编译。
格式:(1)#ifdef 标识符程序段1#else程序段2#endif或#ifdef程序段1#endif当标识符已经定义时,程序段1才参加编译。
格式:(2)#ifndef 标识符格式:(3)#if 表达式li9_7.c使用条件编译可以使目标程序变小,运行时间变短。
预编译使问题或算法的解决方案增多,有助于我们选择合适的解决方案。
第7章预处理程序7.1什么是预处理程序预处理程序是一些行首以#开始的特殊语句,例如:#include,#define等就是预处理语句。
在编译程序的编译过程中,进行其它编译处理(词法分析、语法分析、代码生成、优化和连接等)之前,先进行这些语句的分析处理。
预处理语句使用的目的在于帮助程序员编写出易读、易改、易移植并便于调试的程序。
预处理语句主要有四种:宏定义和宏替换、文件包含、条件编译和行控制。
预处理语句的作用范围是从被定义语句开始直至被解除定义或是到包含它的文件结术为止均有效。
7.2宏定义和宏替换“宏”是借用汇编语言中的概念。
为的是在C语言程序中方便的作一些定义和扩展。
这些语句以#define开头,分为两种:符号常量的宏定义和带参数的宏定义。
1.符号常量的宏定义和宏替换符号常量的宏定义语句是一般格式:#define 标识符字符串其中标识符就叫作宏名称。
注意:标识符与字符串之间不要用…=‟,结尾不要加…;‟。
2.带有参数的宏定义及其替换复杂的宏定义带有参数列表,参数列表中可有不止一个参数,其一般格式:#define 标识符(参数列表) 字符串对带有参数的宏定义进行宏替换时,不仅对宏标识符作字符串替换,还必须作参数的替换。
例如:#define SQ(x) ((x)*(x))那么SQ(a+B)将被宏替换成(a+B)*(a+B)。
宏定义也可嵌套使用,即一个宏定义可用另一个宏定义来定义。
例如:#define SQ(x) ((x)*(x))#define CUBE(x) (SQ(x)*(x))3.宏定义类函数宏定义常用于把直接插入的代码来代替函数,以提高执行效率。
这一类的宏,就称做宏定义类函数,例如:#define MIN(x,y) (((x)<(y))?(x):(y))有了这样的宏之后,就可以直接引用,例如:m=MIN(a,B);这语句将被预处理成:m=(((a)<(B))?(a):(B));7.3文件包含文件包含是指一个程序文件将另一个指定义文件的内容包含进来,用#include语句来说明。
一般有两种格式:(1) #include <文件名>(2) #include 〃文件名〃第一种,用尖括号表示在标准库目录下找该文件;第二种,用双引号表示先在当前目录(源文件所在目录)中找包含文件,若找不到,再到标准库目录中找。
系统的标准库文件都是.h文件。
例如:#include <stdio.h>/* 标准输入输出的基本常量和宏或函数文件*/#include <string.h>/* 串函数文件*/#include <malloc.h>/* 内存分配函数文件*/#include <ctype.h>/* 字符函数文件*/#include <math.h>/* 数学函数库文件*/用文件包含,可以减少重复工作,提高程序正确性,还便于维护修改。
程序员可以把自己常用的一些符号常量、类型定义和带参数的宏定义,以及一些常用自编函数都放在.h文件中,通过#include语句包含引用之。