首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

预处理过程:宏

  • 23-09-22 01:23
  • 4446
  • 13474
blog.csdn.net

本文学习C语言中宏地基本概念,以及编译器在预处理过程中对宏的处理。Hightec编译器版本是tricore v4.9.1.0。

文章目录

  • 1 宏定义
  • 2 对象宏
    • 2.1 简单的对象宏
    • 2.2 多行宏定义
    • 2.3 宏定义的位置
    • 2.4 嵌套宏定义
  • 3 函数宏
    • 3.1 简单的函数宏
    • 3.2 函数宏的参数
  • 4 总结

1 宏定义

在C语言中,宏定义随处可见。比方说Autosar的代码中,或者Simulink生成的代码中,都包含了大量的宏定义。通常来说,在C文件的最开始处,或者头文件中会定义一个宏,然后在后面的代码中如果遇到了同样的片段,预处理器就把这段名字替换成定义好的内容。

宏定义分为两种,对象宏和函数宏。后文会利用编译器来研究这两种宏的基本用法。

2 对象宏

对象宏是一个简单的标识符,之所以称为类对象,是因为它看起来像是使用它的代码中的数据对象,它们通常用来给一个数字取个名字,这样就便于阅读理解。

2.1 简单的对象宏

宏定义用 #define 来定义,例如下面就是定义了一个名为 BUFFER_SIZE 的宏,它背后代表的是数组1024.

#define BUFFER_SIZE 1024
  • 1

可以创建一个简单的C文件,再调用编译器对它进行预处理,就可以直观地看到编译器是怎么处理宏定义的。

首先,创建一个 demo.c 源文件如下;
在这里插入图片描述
C文件中定义了一个宏 BUFFER_SIZE ,数值是1024。后面又把这个宏作为 malloc 函数的参数传入。

通过如下命令行,对 demo.c 文件进行预处理;

tricore-gcc -E demo.c -o demo.i
  • 1

然后打开预处理输出的 demo.i 文件,如下图;
在这里插入图片描述
可以看出,在 demo.i 文件中不再有 #define 字段,并且malloc函数中的参数由 BUFFER_SIZE 变成了它所代表的数值——1024。也就是说,预处理器将 BUFFER_SIZE 这个宏“展开”到了代码中。

2.2 多行宏定义

宏定义在 #define 这一行末尾就结束了,如果需要在多行中定义一个宏,就需要用反斜杠,例如如下的宏定义。

#define NUMBERS 1, 
2, 
3
int x[] = { NUMBERS };
  • 1
  • 2
  • 3
  • 4

也可以用编译器对他处理一下进行验证。demo.c文件改成如下图所示。
在这里插入图片描述
处理后的i文件就是如下所示。
在这里插入图片描述

2.3 宏定义的位置

C源文件中的宏定义一般都是在最开始的地方,因为这样写,预处理器就能一开始就知道有哪些宏。如果宏定义在代码的中间,在处理到这一行之前,预处理器是不知道这个宏的。具体可以看一下下面的例子。

在代码中写下如下图的定义;
在这里插入图片描述
通过命令行对其进行预处理,结果输出的i文件如下;
在这里插入图片描述
可以注意到,由于 #define 是在foo赋值之后的,所以foo等号右边的X没有被预处理器替换为数字4,在后面的编译过程中会因为没定义X而报错。这就提醒了我们,宏定义要写在代码的最开头部分。

2.4 嵌套宏定义

如果宏定义中套了好几层,预处理器也会一层一层地展开宏定义。例如下图中,定义了两个宏。
在这里插入图片描述
图中先把 TABLESIZE 这个宏定义为 BUFSIZE ,再把 BUFSIZE 这个宏定义为1024。用预处理器输出i文件如下。
在这里插入图片描述
最终,等号右边地宏被展开了两次,变成了数字1024。

3 函数宏

除了对象宏以外,C语言中还可以定义一种类似于函数定义的宏,被称为函数宏。函数宏和对象宏的一个重要区别在于,看名字里面有没有括号。

3.1 简单的函数宏

函数宏也是用 #define 来定义的,例如下面的指令把 lang_init() 函数定义为 c_init() 。

#define lang_init() c_init()
  • 1

需要注意的是,预处理器在代码中只有遇到了带括号的函数字段,才会展开函数宏。如果只是名字和函数宏名字相同的变量,就不会做处理。这一点也可以调用预处理器来验证一下。

首先,将 demo.c 文件修改如下;
在这里插入图片描述
通过预处理器对其处理,输出的i文件如下;
在这里插入图片描述
可以看出,函数宏 lang_init() 被展开为 c_init() ,但是赋值x的语句右边的 lang_init 由于没有带括号,就不会被处理。

另外还需要指出,在 #define 指令中,括号必须紧跟在函数名称后面,否则预处理后的结果就不是上图所示的那样展开。

3.2 函数宏的参数

函数宏也可以像真正的函数一样,在括号中带有参数。如果有多个参数,就用逗号隔开。

例如下图所示的函数宏,用来比较两个数的大小,并返回较小的那个数字。
在这里插入图片描述
通过预处理器对其处理,输出的i文件如下;
在这里插入图片描述
在展开函数宏的时候,把其中的参数也一起展开了。例如第2行的 x = min(a, b); ,第一个参数a对应着宏定义的参数X,第一个参数b对应着宏定义的参数Y。展开后,a和b也处于X和Y对应的位置。

4 总结

本文学习了一些C语言宏定义的基本用法,并且用编译器输出i文件对其进行验证,有了直观的认识。在编译手册中,宏定义还有很多复杂的用法和注意点,博主认为不需要一次性全搞懂,等到遇到了对应的问题后再进行查阅即可。

>>返回个人博客总目录

注:本文转载自blog.csdn.net的chhttty的文章"https://blog.csdn.net/u013288925/article/details/114895695"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top