【C++
目录
1.宏格式:
2.无参宏详解:
3.宏和typedef:
4.有参宏详解:
5.无参宏说明:
6.有参宏说明:
7.宏的优点:
8.宏的缺点:
9.define与const的区别的简单总结:
1.宏格式:
- 每个#define行由三部分组成:第一部分是指令 #define 自身,“#”表示这是一条预处理命令,“define”为宏命令。
- 第二部分为宏,一般为缩略语,其名称(宏名)一般大写,而且不能有空格,遵循C变量命令规则。
- “替换文本”可以是任意常数、表达式、字符串等。
- 在预处理工作过程中,代码中所有出现的“宏名”,都会被“替换文本”替换。
- 这个替换的过程被称为“宏代换”或“宏展开”(macro expansion)。
- “宏代换”是由预处理程序自动完成的。在C语言中,“宏”分为两种:无参数 和 有参数。
2.无参宏详解:
- 无参宏是指宏名之后不带参数,最简单的宏就是无参宏。
- 一种最简单的宏的形式如下: #define 宏名 替换文本
-
#define M 10 // 宏定义 #define PI 3.14 //宏定义#define H hi;int arr[M]; // 会被替换为: int a[5] int b = M; // 会被替换为: int b = 5 printf("%d",H) ; //会输出: hi; printf("PI = %.2f\n", PI); // 输出结果为: PI = 3.14
- 注意宏不是语句,结尾不需要加“;”,否则会被替换进程序中,如上例: 输出: hi;
- 如果要写宏不止一行,则在结尾加反斜线符号使得多行能连接上,如
-
#define HELLO "hello the wo\rld"printf("HELLO is %s\n", HELLO); //输出结果为: HELLO is hello the wo rld
- 宏可以嵌套,但不参与运算:
#define M 5 // 宏定义 #define MM M * M // 宏的嵌套printf("MM = %d\n", MM); // MM 被替换为: MM = M * M, 然后又变成 MM = 5 * 5
- 宏定义必须写在函数之外,其作用域是 #define 开始,到源程序结束。如果要提前结束它的作用域则用 #undef 命令,如:
-
#define M 5 // 宏定义 printf("M = %d\n", M); // 输出结果为: M = 5 #define M 100 // 取消宏定义 printf("M = %d\n", M); // error:… main.c:138:24: Use of undeclared identifier 'M'
3.宏和typedef:
- 宏定义只是简单的字符串代换,在预处理阶段完成。
- 而typede不是简单的字符串代换,而是可以用来做类型说明符的重命名的,类型的别名可以具有类型定义说明的功能,在编译阶段完成的。
4.有参宏详解:
- C语言中宏是可以有参数的,这样的宏就成了外形与函数相似的类函数宏(function-like macro),如:
- 和函数类似,在宏定义中的参数成为形式参数,在宏调用中的参数成为实际参数。
- 而且和无参宏不同的一点是,有参宏在调用中,不仅要进行宏展开,而且还要用实参去替换形参。
#define COUNT(M) M * M //定义有参宏
int x = 6;
printf("COUNT = %d\n", COUNT(x + 1));// 输出结果: COUNT = 13
printf("COUNT = %d\n", COUNT(++x)); // 输出结果: COUNT = 56 //warning:... main.c:161:34: Multiple unsequenced modifications to 'x'
这两个结果和调用函数的方法的结果差别很大,因为如果是像函数那样的话,COUNT(x + 1)应该相当于COUNT(7),结果应该是 7 * 7 = 49,但输出结果却是21。原因在于,预处理器不进行技术,只是进行字符串替换,而且也不会自动加上括号(),所以COUNT(x + 1)被替换为 COUNT(x + 1 * x + 1),代入 x = 6,即为 6 + 1 * 6 + 1 = 13。而解决办法则是:尽量用括号把整个替换文本及其中的每个参数括起来。
5.无参宏说明:
说明:
(1)宏名一般用大写。
(2)使用宏可提高程序的通用性和易读性,减少不一致性,减少输入错误和便于修改。例如:数组大小常用宏定义。
(3)预处理是在编译之前的处理,而编译工作的任务之一就是语法检查,预处理不做语法检查。
(4)宏定义末尾不加分号。
(5)宏定义写在函数的花括号外边,作用域为其后的程序,通常在文件的最开头。
(6)可以用#undef命令终止宏定义的作用域。
(7)宏定义可以嵌套。
(8)字符串" "中永远不包含宏。
(9)宏定义不分配内存,变量定义分配内存。
(10)宏定义不存在类型问题,它的参数也是无类型的。
6.有参宏说明:
1)实参如果是表达式容易出问题
#define S(r) r*r
area=S(a+b);第一步换为area=r*r;第二步被换为area=a+b*a+b;
正确的宏定义是#define S(r) ((r)*(r))
(2)宏名和参数的括号间不能有空格。
(3)宏替换只作替换,不做计算,不做表达式求解。
(4)函数调用在编译后程序运行时进行,并且分配内存。宏替换在编译前进行,不分配内存。
(5)宏的哑实结合不存在类型,也没有类型转换。
(6)函数只有一个返回值,利用宏则可以设法得到多个值。
(7)宏展开使源程序变长,函数调用不会。
(8)宏展开不占运行时间,只占编译时间,函数调用占运行时间(分配内存、保留现场、值传递、返回值)。
7.宏的优点:
.1.增强代码的复用性。
2.提高性能。
8.宏的缺点:
- 无法对宏定义中的变量进行类型检查;
- 未加括号带来的边界效应;
- 在宏定义中出现++或—之类的操作符的时候,即使加括号,也无法避免其中的问题;
- 不方便调试,在预处理阶段就进行了替换;
- 代码可读性差,维护性差,容易误用;
9.define与const的区别的简单总结:
- define定义的变量,是Compile-Time时期的变量,系统在编译时候,就将其全部替换,而不会对其变量进行类型等属性检查,相对不是很安全,可能存在潜在的问题,而没有发现.
- 正因为其仅仅是编译时期替换,所以其定义的变量,是不会在运行时候分配内存的,不占用内存空间.
- const定义的变量,是 Run-Time时期的变量,如果类型不匹配,系统在运行时候,就会发现并提示或报错,对应的,const变量在运行时期,也是一种变量,系统会为其分配内存.
- 参考文章链接:
【C++
目录
1.宏格式:
2.无参宏详解:
3.宏和typedef:
4.有参宏详解:
5.无参宏说明:
6.有参宏说明:
7.宏的优点:
8.宏的缺点:
9.define与const的区别的简单总结:
1.宏格式:
- 每个#define行由三部分组成:第一部分是指令 #define 自身,“#”表示这是一条预处理命令,“define”为宏命令。
- 第二部分为宏,一般为缩略语,其名称(宏名)一般大写,而且不能有空格,遵循C变量命令规则。
- “替换文本”可以是任意常数、表达式、字符串等。
- 在预处理工作过程中,代码中所有出现的“宏名”,都会被“替换文本”替换。
- 这个替换的过程被称为“宏代换”或“宏展开”(macro expansion)。
- “宏代换”是由预处理程序自动完成的。在C语言中,“宏”分为两种:无参数 和 有参数。
2.无参宏详解:
- 无参宏是指宏名之后不带参数,最简单的宏就是无参宏。
- 一种最简单的宏的形式如下: #define 宏名 替换文本
-
#define M 10 // 宏定义 #define PI 3.14 //宏定义#define H hi;int arr[M]; // 会被替换为: int a[5] int b = M; // 会被替换为: int b = 5 printf("%d",H) ; //会输出: hi; printf("PI = %.2f\n", PI); // 输出结果为: PI = 3.14
- 注意宏不是语句,结尾不需要加“;”,否则会被替换进程序中,如上例: 输出: hi;
- 如果要写宏不止一行,则在结尾加反斜线符号使得多行能连接上,如
-
#define HELLO "hello the wo\rld"printf("HELLO is %s\n", HELLO); //输出结果为: HELLO is hello the wo rld
- 宏可以嵌套,但不参与运算:
#define M 5 // 宏定义 #define MM M * M // 宏的嵌套printf("MM = %d\n", MM); // MM 被替换为: MM = M * M, 然后又变成 MM = 5 * 5
- 宏定义必须写在函数之外,其作用域是 #define 开始,到源程序结束。如果要提前结束它的作用域则用 #undef 命令,如:
-
#define M 5 // 宏定义 printf("M = %d\n", M); // 输出结果为: M = 5 #define M 100 // 取消宏定义 printf("M = %d\n", M); // error:… main.c:138:24: Use of undeclared identifier 'M'
3.宏和typedef:
- 宏定义只是简单的字符串代换,在预处理阶段完成。
- 而typede不是简单的字符串代换,而是可以用来做类型说明符的重命名的,类型的别名可以具有类型定义说明的功能,在编译阶段完成的。
4.有参宏详解:
- C语言中宏是可以有参数的,这样的宏就成了外形与函数相似的类函数宏(function-like macro),如:
- 和函数类似,在宏定义中的参数成为形式参数,在宏调用中的参数成为实际参数。
- 而且和无参宏不同的一点是,有参宏在调用中,不仅要进行宏展开,而且还要用实参去替换形参。
#define COUNT(M) M * M //定义有参宏
int x = 6;
printf("COUNT = %d\n", COUNT(x + 1));// 输出结果: COUNT = 13
printf("COUNT = %d\n", COUNT(++x)); // 输出结果: COUNT = 56 //warning:... main.c:161:34: Multiple unsequenced modifications to 'x'
这两个结果和调用函数的方法的结果差别很大,因为如果是像函数那样的话,COUNT(x + 1)应该相当于COUNT(7),结果应该是 7 * 7 = 49,但输出结果却是21。原因在于,预处理器不进行技术,只是进行字符串替换,而且也不会自动加上括号(),所以COUNT(x + 1)被替换为 COUNT(x + 1 * x + 1),代入 x = 6,即为 6 + 1 * 6 + 1 = 13。而解决办法则是:尽量用括号把整个替换文本及其中的每个参数括起来。
5.无参宏说明:
说明:
(1)宏名一般用大写。
(2)使用宏可提高程序的通用性和易读性,减少不一致性,减少输入错误和便于修改。例如:数组大小常用宏定义。
(3)预处理是在编译之前的处理,而编译工作的任务之一就是语法检查,预处理不做语法检查。
(4)宏定义末尾不加分号。
(5)宏定义写在函数的花括号外边,作用域为其后的程序,通常在文件的最开头。
(6)可以用#undef命令终止宏定义的作用域。
(7)宏定义可以嵌套。
(8)字符串" "中永远不包含宏。
(9)宏定义不分配内存,变量定义分配内存。
(10)宏定义不存在类型问题,它的参数也是无类型的。
6.有参宏说明:
1)实参如果是表达式容易出问题
#define S(r) r*r
area=S(a+b);第一步换为area=r*r;第二步被换为area=a+b*a+b;
正确的宏定义是#define S(r) ((r)*(r))
(2)宏名和参数的括号间不能有空格。
(3)宏替换只作替换,不做计算,不做表达式求解。
(4)函数调用在编译后程序运行时进行,并且分配内存。宏替换在编译前进行,不分配内存。
(5)宏的哑实结合不存在类型,也没有类型转换。
(6)函数只有一个返回值,利用宏则可以设法得到多个值。
(7)宏展开使源程序变长,函数调用不会。
(8)宏展开不占运行时间,只占编译时间,函数调用占运行时间(分配内存、保留现场、值传递、返回值)。
7.宏的优点:
.1.增强代码的复用性。
2.提高性能。
8.宏的缺点:
- 无法对宏定义中的变量进行类型检查;
- 未加括号带来的边界效应;
- 在宏定义中出现++或—之类的操作符的时候,即使加括号,也无法避免其中的问题;
- 不方便调试,在预处理阶段就进行了替换;
- 代码可读性差,维护性差,容易误用;
9.define与const的区别的简单总结:
- define定义的变量,是Compile-Time时期的变量,系统在编译时候,就将其全部替换,而不会对其变量进行类型等属性检查,相对不是很安全,可能存在潜在的问题,而没有发现.
- 正因为其仅仅是编译时期替换,所以其定义的变量,是不会在运行时候分配内存的,不占用内存空间.
- const定义的变量,是 Run-Time时期的变量,如果类型不匹配,系统在运行时候,就会发现并提示或报错,对应的,const变量在运行时期,也是一种变量,系统会为其分配内存.
- 参考文章链接: