文章目录一、#define1.#define 定义常量2.#define 定义宏当用文本代替表示的内容含有参数时#define就形成了宏★宏的特点二、条件编译1)#if... #elif ... #else ... #endif2)#if defined() ... #endif #ifdef ... #endif3)#if !defined() ... #endif #ifndef ... #endif三、头文件的包含#includeadd.h—会先在源文件所在目录下查找如果文件未找到就会去标准库里查找#include—直接去标准库里查找一、#define#define实现的就是文本的代替表示即#define x y -用文本x代替表示y的内容y的内容什么都可以可以是常量、变量、表达式或者几段代码等等都可以1.#define 定义常量#define M 100 int main() { printf(%d\n,M); return 0; }文本M代替表示的是常量值100所以打印的值是1002.#define 定义宏当用文本代替表示的内容含有参数时#define就形成了宏#define name(paramen-tlist) stuff#define 名称(参数,参数) 含参内容左边这一块是文本右边这一块是文本表示的内容由于含有参数代替时是左边含参的文本代替表示右边含参的内容但其本质还是不变的就是文本对内容的替换只不过里面含有了参替换时要根据参数将参数代上去替换得到此参数下的文本和此参数下其对应的代替内容然后就可以知道此参数下的文本代替的值是什么了★宏的特点其实说是参数其实宏的参数是什么都能传因为宏的传参本质上也是文本式替换操作对传的内容都视为文本式的对表达式文本不会算好再替换(因为视为纯文本)而是文本纯替换好后才开始对内容进行计算所以根据它的特点要注意一下几点2.1.参数传过去替换的过程中是不加以任何计算的参数原原本本传过去传完后才开始计算定义一个宏用来求平方 #define SQUARE(n) n*n 将含参表达式n*n这个内容替换为了SQUARE(n) 这个有参数结合的文本 int main() { int ret1,ret2 0; ret1 SQUARE(6); printf(%d\n, ret1);//36 ret2 SQUARE(51); printf(%d\n, ret2);//11 return 0; }因为宏传过去的过程中是不加任何计算的全部过去后才开始计算的所以还原SQUARE(51)此文本代替的内容为51*51 11,所以定义时(n)*(n)每一个参数都要加上括号(51)*(51) 36这样就没问题了还有一个例子定义一个宏用来求一个数的2倍 #define DOUBLE(x) ((x)(x)) int main() { int ret 0; ret 10 * DOUBLE(5); printf(%d\n, ret);//100 10*((5)(5)) 100 如果(x)(x)外层不加括号: - 10*(5)(5) 55 return 0; }所以内每一个x都要有括号括外x构成的整体外部也要有括号括总之写宏时不要吝啬括号2.2.宏的参数在宏体如果是出现多次的话那么当传过来的参数是带有副作用的表达式时参数都换成副作用表达式副作用就不是预想的只产生一次的了而是会产生多次写一个宏求2个数的较大值 #define MAX(X,Y) ((X)(Y)?(X):(Y)) int main() { int a 3; int b 5; int m MAX(a, b); 宏传参传过去里面全替换后: - int m ((a)(b)?(a):(b)); 选择语句选择执行(b) 1.后置下表达式算完再 —— a 3 b 5 ,表达式比较完后a后为4;b后为6,选择执行(b)语句 2.执行(b)语句,b为后置先把值赋给m, m b 6 ,然后b为7 printf(m %d\n, m);//6 printf(a %d\n, a);//4 printf(b %d\n, b);//7 return 0; }2.3.宏都是替换式过去文本式替换什么都能替换什么都能传宏传类型如下#includestdlib.h #define Malloc(n,type) (type*)malloc(n*sizeof(type)) int main() { int* p (int*)malloc(10 * sizeof(int)); 这里宏传的参是类型 int* ptr Malloc(10, int); ——int* ptr (int*)malloc(10*sizeof(int)); }2.4.宏的参数去找替换时它至少要按符号单位去替换的举个例子比如下图中要用参数传来的int替换函数名标识符type_max中的type因为type与_max构成了标识符符号单位int来替换时是做不到替换标识符部分的因为它替换时的最小单位是符号要换就要type_max这个标识符而不能换里面的type标识符的一部分所以我们可以用##操作符它可以实现把符号切割创建更小的合法的符号单位即type##_max中参数int来替换时此时type是一个合法的符号单位可以完成替换即int##_max替换好后##又会将两端的符号单位合并合并成一个符号单位—int_max此时就完成了参数在名字里部分的替换形成了由参数部分构成的函数名这样就可以实现声明多种不同函数类型的函数(它们函数名是不同的)实现批量制造函数了定义一个声明函数的宏 声明函数的模具 #define GENERIC_MAX(type) \ type type##_max(type x, type y)\ { \ return xy?x:y; \ } 用宏替换完后是一个函数的声明 利用宏实现可以一句代码批量声明函数 GENERIC_MAX(int); int int_max(int x, int y){ return xy?x:y;} ——即: // int int_max(int x, int y) //{ // return x y ? x : y;\ //} int main() { int r int_max(3, 5); printf(%d\n, r);//5 return 0; }二、条件编译1)#if... #elif ... #else ... #endif2)#if defined() ... #endif #ifdef ... #endif3)#if !defined() ... #endif #ifndef ... #endif判断是否被定义:#define MAX 1 int main() { #ifdef用来判断符号是否被程序员定义过: 如果MAX被定义过为真 #ifdef MAX printf(MAX已定义\n); 如果MAX未被定义 #else printf(MAX未定义\n); #endif return 0; }1.每一个#if(包括#ifdef 、#ifndef)都要有 #endif 匹配的都要有一一对应 (elif不属于#if)2.#if到对应#endif的整块区域为一个条件编译判断区不用{}括因为#endif会自动找#if匹配3.#这些条件预处理的指令判断为假的部分在源文件预处理中不会执行在预处理后的预编译代码.i中也已经是直接删掉了那种不会出现在后面的工程文件里它最多只是在源文件中露了面的那种(跳过没去执行)补充#undef用于移除一个宏定义)#define MAX 100 int main() { printf(%d\n,MAX);100 #undef MAX printf(%d\n,MAX);MAX未定义 }三、头文件的包含#includeadd.h与#includeadd.h#includeadd.h—会先在源文件所在目录下查找如果文件未找到就会去标准库里查找#includeadd.h—直接去标准库里查找为避免嵌套文件时头文件的重复包含引入在每个头文件的开头写#ifndef __TEST_H__ #define __TSET_H__ 头文件的内容 #endif或#pragma once 头文件内容