C语言-宏定义2.0

无参宏

这些宏没有参数,它们只是简单地将一个特定的文本替换为另一个文本

无参宏意味着使用宏的时候,无需指定任何参数,比如:

#define PI          3.14
#define SCREEN_SIZE 800*480*4 
int main()
{
    // 在代码中,可以随时使用以上无参宏,来替代其所代表的表达式:
    printf("圆周率: %f\n", PI); 
    mmap(NULL, SCREEN_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, ...);
}

注意到,上述代码中,除了有自定义的宏,还有系统预定义的宏:

// 自定义宏:
#define PI          3.14
#define SCREEN_SIZE 800*480*4 

自定义宏:

PI:将3.14定义为一个名为PI的宏,用于表示圆周率。
SCREEN_SIZE:将表达式800*480*4定义为一个名为SCREEN_SIZE的宏,用于表示屏幕尺寸。


// 系统预定义宏
#define NULL ((void *)0)
#define PROT_READ	0x1	/* Page can be read.  */
#define PROT_WRITE	0x2	/* Page can be written.  */
#define MAP_SHARED	0x01	/* Share changes.  */

系统预定义宏:

NULL:将地址0强制转换为void*类型,并定义为一个名为NULL的宏,通常用于表示空指针。
PROT_READ:将十六进制数0x1定义为一个名为PROT_READ的宏,表示页面可读。
PROT_WRITE:将十六进制数0x2定义为一个名为PROT_WRITE的宏,表示页面可写。
MAP_SHARED:将十六进制数0x01定义为一个名为MAP_SHARED的宏,表示共享页面的更改。

宏的最基本特征是进行直接文本替换,以上代码被替换之后的结果是:

int main()
{
    printf("圆周率: %f\n", 3.14); 
    mmap(((void *)0), 800*480*4, 0x1|0x2, 0x01, ...);
}

带参宏

带参宏意味着宏定义可以携带“参数”,从形式上看跟函数很像,例如:

#define MAX(a, b)   a>b ? a : b
#define MIN(a, b)   a<b ? a : b

以上的MAX(a,b) 和 MIN(a,b) 都是带参宏,不管是否带参,宏都遵循最初的规则,即宏是一段待替换的文本

例如在以下代码中,宏在预处理阶段都将被替换掉:

int main()
{
    int x = 100, y = 200;
    printf("最大值:%d\n", MAX(x, y));
    printf("最小值:%d\n", MIN(x, y));
    // 以上代码等价于:
    // printf("最大值:%d\n", x>y ? x : y);
    // printf("最小值:%d\n", x<y ? x : y);
}
  • 带参宏的特点:
    1. 直接文本替换,不做任何语法判断,更不做任何中间运算。
    2. 宏在编译的第一个阶段就被替换掉,运行中不存在宏。
    3. 宏将在所有出现它的地方展开,这一方面浪费了内存空间,另一方面有节约了切换时间。

带参宏的副作用

由于宏仅仅做文本替换,中间不涉及任何语法检查、类型匹配、数值运算,因此用起来相对函数要麻烦很多。例如:

#define MAX(a, b) a>b ? a : b

int main()
{
    int x = 100, y = 200;
    printf("最大值:%d\n", MAX(x, y==200?888:999));
}

直观上看,无论 y 的取值是多少,表达式 y==200?888:999 的值一定比 x 要大,但由于宏定义仅仅是文本替换,中间不涉及任何运算,因此等价于:

printf("最大值:%d\n", x>y==200?888:999 ? x : y==200?888:999);

可见,带参宏的参数不能像函数参数那样视为一个整体,整个宏定义也不能视为一个单一的数据,事实上,不管是宏参数还是宏本身,都应被视为一个字串,或者一个表达式,或者一段文本,因此最基本的原则是:

  • 将宏定义中所有能用括号括起来的部分,都括起来,比如:
#define MAX(a, b) ((a)>(b) ? (a) : (b))

相关推荐

  1. C语言】(8)定义

    2024-05-01 05:58:04       56 阅读
  2. 常用的C语言定义

    2024-05-01 05:58:04       63 阅读
  3. C语言-定义2.0

    2024-05-01 05:58:04       39 阅读
  4. C语言12 定义、内存

    2024-05-01 05:58:04       25 阅读
  5. C语言定义中#和##使用详解

    2024-05-01 05:58:04       58 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-05-01 05:58:04       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-05-01 05:58:04       106 阅读
  3. 在Django里面运行非项目文件

    2024-05-01 05:58:04       87 阅读
  4. Python语言-面向对象

    2024-05-01 05:58:04       96 阅读

热门阅读

  1. Rust 命令行参数解析指南

    2024-05-01 05:58:04       32 阅读
  2. 动态提示工具插件库——tippyjs

    2024-05-01 05:58:04       30 阅读
  3. wetrtc简介

    2024-05-01 05:58:04       33 阅读
  4. 微信小程序个人开放服务类目表

    2024-05-01 05:58:04       31 阅读
  5. 数据库学习之用户管理和权限问题

    2024-05-01 05:58:04       32 阅读
  6. 每日写题(第八天)

    2024-05-01 05:58:04       30 阅读
  7. IP && 端口号

    2024-05-01 05:58:04       29 阅读
  8. 常见的 HTML 标准

    2024-05-01 05:58:04       26 阅读
  9. C++11 设计模式7 策略模式 ,Strategy

    2024-05-01 05:58:04       27 阅读
  10. 真渗透小结

    2024-05-01 05:58:04       29 阅读
  11. vscode相关插件使用----持续更新中

    2024-05-01 05:58:04       28 阅读
  12. cartographer问题处理

    2024-05-01 05:58:04       37 阅读