建设一个网站需要哪些员工,广州市服务好的网站制作排名,网站上面的水印怎么做的,建设银行滇龙行网站C语言中的宏函数与宏定义  从开始写C语言到生成执行程序的流程大致如下#xff1a; 
预处理工作是系统引用预处理程序对源程序中的预处理部分做处理#xff0c;而预处理部分是指以“#”开头的、放在函数之外的、一般放在源文件的前面的预处理命令#xff0c;如#xff1a;包… C语言中的宏函数与宏定义  从开始写C语言到生成执行程序的流程大致如下 
预处理工作是系统引用预处理程序对源程序中的预处理部分做处理而预处理部分是指以“#”开头的、放在函数之外的、一般放在源文件的前面的预处理命令如包括命令 #include宏命令 #define 等合理地利用预处理功能可以使得程序更加方便地阅读、修改、移植、调试等也有利于模块化程序设计。 
宏定义是比较常用的预处理指令即使用“标识符”来表示“替换列表”中的内容。标识符称为宏名在预处理过程中预处理器会把源程序中所有宏名替换成宏定义中替换列表中的内容 
常见的宏定义有两种不带参数的宏定义和带参数的宏定义。 
1、无参宏定义 1.1 无参数宏定义的格式 #define 标识符 替换列表 替换列表可以是数值常量、字符常量、字符串常量等故可以把宏定义理解为使用标识符表示一常量或称符号常量。 
1.2 使用说明 可以不在行首但只允许它前面有空格符。例如  
#define PI 3.1416 //正确该行#前允许有空格 int a;#define N 5 //错误该行#前不允许有空格外的其他字符 2) 标识符和替换列表之间不能加赋值号 替换列表后不能加分号 
#define N 5 //虽语法正确但预处理器会把N替换成5 int a[N]; //错误因为宏替换之后为 int a[5]; #define N 5; //虽语法正确但会把N替换成5; int a[N]; //语法错误宏替换后为int a[5;];错误 3) 由于宏定义仅是做简单的文本替换故替换列表中如有表达式必须把该表达式用括号括起来否则可能会出现逻辑上的“错误”。例如 
#define N 32 int rN*N; 
宏替换后为 int r32*32; //r11 如果采用如下形式的宏定义 
#define N (32) int rN*N; 
则宏替换后为: int r(32)*(32); //r25 4) 当替换列表一行写不下时可以使用反斜线\作为续行符延续到下一行。例如 
#define USA “The United  States of  America” 
printf(“%s\n”,USA); 
//输出结果为:The United States of America 该宏定义中替换列表为字符串常量如果该串较长或为了使替换列表的结构更清晰可使用续行符 \ 把该串分若干行来写除最后一行外每行行尾都必须加续行符 \。注意续行符后直接按回车键换行不能含有包括空格在内的任何字符否则是错误的宏定义形式。 
5)宏可以嵌套但不参与运算 
#define M 5 // 宏定义 #define MM M * M // 宏的嵌套 printf(“MM  %d\n”, MM); // MM 被替换为: MM  M * M, 然后又变成 MM  5 * 5 实际的 5 * 5 相乘过程在编译阶段完成而不是在预处理器工作阶段完成宏不进行运算它只是按照指令进行文字的替换操作无论替换文本中是常数、表达式或者字符串等预处理程序都不做任何检查如果出现错误只能是被宏代换之后的程序在编译阶段发现。 
6)宏定义必须写在函数之外作用域从 #define 开始到源程序结束。如果要提前结束它的作用域则用 #undef 命令 
#define M 5 // 宏定义 printf(“M  %d\n”, M); // 输出结果为 M  5 #undef M // 取消宏定义 printf(“M  %d\n”, M); // error:… main.c:138:24: Use of undeclared identifier ‘M’ 7)可以用宏定义表示数据类型可以使代码简便 
#define STU struct Student // 宏定义STU struct Student{ // 定义结构体Student char *name; int sNo; }; STU stu  {“Jack”, 20}; // 被替换为struct Student stu  {“Jack”, 20}; printf(“name: %s, sNo: %d\n”, stu.name, stu.sNo); 8)#define 与 typedef 的区别 
两者都可以用来表示数据类型 
#define INT1 int typedef int INT2; 
两者是等效的调用也一样 INT1 a1  3; INT2 a2  5; 但当如下使用时问题就来了 
#define INT1 int * typedef int * INT2; INT1 a1, b1; INT2 a2, b2; b1  m; //… main.c:185:8: Incompatible pointer to integer conversion assigning to ‘int’ from ‘int *’; remove  b2  n; // OK INT1 a1, b1; 被宏代换后为 int * a1, b1; 
即定义的是一个指向int型变量的指针 a1 和一个int型的变量b1. 
INT2 a2, b2;表示定义的是两个变量a2和b2这两个变量的类型都是INT2的也就是int *的 
两个都是指向int型变量的指针 
所以两者区别在于宏定义只是简单的字符串代换在预处理阶段完成。而typede不是简单的字符串代换而是可以用来做类型说明符的重命名的类型的别名可以具有类型定义说明的功能在编译阶段完成的。 
2、带参宏定义 2.1 带参数宏定义的格式 #define 标识符(参数1,参数2,…,参数n) 替换列表 例如求两个参数中最大值的带参宏定义为 
#define MAX(a,b) ((a)(b)?(a) : (b)) int cMAX(5,3); 
//预处理器会将带参数的宏替换成如下形式 int c((5)(3)?(5) : (3)); 故计算结果c5。 2.2 使用说明 
标识符与参数表的左括号之间不能有空格否则预处理器会把该宏理解为普通的无参宏定义 
#define MAX (a,b) ( (a)  (b) ? (a) : (b) ) //错误的带参宏定义格式 #define SUM (a,b) a  b //定义有参宏 printf(“SUM  %d\n”, SUM(1,2)); //调用有参宏。Build Failed 因为 SUM 被替换为(a,b) a  b 和无参宏不同的一点是有参宏在调用中不仅要进行宏展开而且还要用实参去替换形参 
宏替换列表中每个参数及整个替换列表都必须用一对小括号 () 括起来否则可能会出现歧义 
#include stdio.h #define MUL(a,b) (a*b) int main (void) { int c; cMUL(3,51); printf(“c%d\n”,c); return 0; } 
//修改后 #include stdio.h #define MUL(a,b) ((a)*(b))//修改处1 int main (void) { int c; cMUL(3,(51);//修改处2 printf(“c%d\n”,c); return 0; } 3、带参宏定义与函数调用的区别 带参宏定义 函数调用 调用发生时间 预处理阶段 程序运行期间 参数类型检查 
在预处理阶段对带参宏调用中的参数不做检查。即宏定义时不需要指定参数类型适用于多种数据类型。 函数参数类型检查严格。程序在编译阶段需要检查实参与形参个数是否相等及类型是否匹配或兼容若参数个数不相同或类型不兼容则会编译不通过。 参数是否需要空间 宏替换仅是简单的文本替换且替换完就把宏名对应标识符删除掉不需要分配空间。 需要为形参分配空间并把实参的值复制一份赋给形参分配的空间中。 运行速度 宏替换仅是简单文本替换不做任何语法或逻辑检查。速度较快 函数在编译阶段需要检查参数个数是否相同、类型等是否匹配等多个语法函数在运行阶段参数需入栈和出栈操作速度相对较慢。 代码长度 
宏替换是文本替换即如果需替换的文本较长则替换后会影响代码长度 函数不会影响代码长度 故使用较频繁且代码量较小的功能一般采用宏定义的形式比采用函数形式更合适。 
#define getchar() getc(stdin) 故调用该宏时需要加括号即传空参数getchar()。 
4、头文件中常用的宏定义 1防止头文件被重复包含 
#ifndef cTest_Header_h #define cTest_Header_h //头文件内容 #endif 在我们常用的 stdio.h 头文件中也可以见到很多宏定义如 
备注#ifndef 和 #endif 要一起使用如果丢失#endif可能会报错。 
#define BUFSIZ 1024 //缓冲区大小 #define EOF (-1) //表文件末尾 #ifndef SEEK_SET #define SEEK_SET 0 //表示文件指针从文件的开头开始 #endif #ifndef SEEK_CUR #define SEEK_CUR 1 //表示文件指针从现在的位置开始 #endif #ifndef SEEK_END #define SEEK_END 2 //表示文件指针从文件的末尾开始 #endif 知识补充 
#ifndef是if not defined的简写是宏定义的一种它是可以根据是否已经定义了一个变量来进行分支选择一般用于调试防止头文件的重复包含和编译 
第一种 #ifndef x#define x程序段1#else程序段2#endif//终止if//先测试x是否被宏定义过 //如果x没有被宏定义过定义x并编译程序段 1 //如果x已经定义过了则编译程序段2的语句“忽视”程序段 1 
第二种 
语句1 #ifndef 标识1 
语句2 #define 标识1 
语句3 #endif 语句4 ……语句5 ……//如果标识1没有被定义则重定义标识1即执行语句2、语句3;如果标识1已经被定义则直接跳过语句2、语句3直接执行语句4、语句5、…… 
第三种 
//例如要编写头文件test.h在头文件开头写上两行 #ifndef _TEST_H#define _TEST_H //一般是文件名的大写头文件结尾写上一行#endif当第一次包含test.h时由于没有定义_TEST_H条件为真这样就会执行#ifndef _TEST_H和#endif之间的代码当第二次包含test.h时前面已经定义了_TEST_H条件为假#ifndef _TEST_H和#endif之间的代码也就不会再次被包含这样就避免了重定义。 
标识在理论上来说可以是自由命名的但每个头文件的这个“标识”都应该是唯有的。标识的命名规则一般是头文件名全大写前面加下划线并把文件名中的“.”也变成下划线如stdio.h 
#ifndef _STDIO_H 
#define _STDIO_H 
… 
#endif 
5、宏中#和##的用法 使用#把宏参数变为一个字符串例如如果 a 是一个宏的形参则替换文本中的 #a 则被系统转化为 “a”。而这个转化的过程成为 “字符串化stringizing” 
#define SUM(a,b) printf(#a   “#b”  %d\n,((a)  (b))) //宏定义运用 # 运算符 SUM(1  2, 3  4); //宏调用 //输出结果1  2  3  4  10 
调用宏时用 1  2 代替 a用 3  4 代替b则替换文本为 printf(“1  2” ”  ” “3  4” ”  %d\n”,((1  2)  (3  4))) 接着字符串连接功能将四个相邻的字符串转换为一个字符串 “1  2  3  4  %d\n” 用##把两个宏参数贴合在一起又称为“预处理器的粘合剂Preprocessor Glue” 
#define NAME(n) num ## n //宏定义使用 ## 运算符 int num0  10; printf(“num0  %d\n”, NAME(0)); //宏调用 
NAME(0)被替换为 num ## 0被粘合为 num0。 可变宏在这里不进行介绍 
参考 
宏定义无参宏定义和带参宏定义C语言宏定义详解 
详解宏定义#define___Sunshine_的博客-CSDN博客_宏定义 
C语言宏定义、宏函数、内置宏与常用宏_Apollon_krj的博客-CSDN博客_c语言宏函数