c中对宏的理解(面试题)

news2024/11/28 17:36:45

1、gcc的编译过程:预处理、编译、汇编、链接

在这里插入图片描述

预处理:宏替换、删除注释、头文件包含、条件编译 -E (不会发生报错)生成预编译文件
将 01_code.c文件使用 gcc -E 01_code.c -o 01.i生成预编译文件01.i
在这里插入图片描述
可以10行的源文件看见生成800多行的预编译文件
在这里插入图片描述

编译:将预编译之后的文件编译成汇编文件
在这里插入图片描述
在这里插入图片描述

汇编:将汇编文件生成二进制文件
在这里插入图片描述

在这里插入图片描述

链接:将工程中的各个二进制文件+库函数+启动文件 生成可执行文件

edu@edu:~/work/c/day_03$ gcc 01.o -o 01

在这里插入图片描述

或者可以直接由预编译文件一步到位

在这里插入图片描述

2、宏的了解

使用关键字define叫做宏

#define MA 3                          //宏的定义形式(宏定义)

在预处理的时候使用 3 代替所有MA出现的位置(宏展开)
注意:不要再宏后面加 分号

#define MA 3;                          //错误的宏定义形式
if (MA>2){   //这个表达式中 就会出现 3; > 2这样的情况,所以加分号这种宏定义形式是错误的
   printf("大于\n");
}

3、不带参数的宏

宏的定义范围:是从定义处开始当前文件结束 都有效
#under可以结束宏的作用域(但是这个是不常用的)
宏没有归属,只有在当前文件中有效


#include <stdio.h>
void test06()
{
#define N 100 // 宏没有归属感,只要不影响使用,可以定义在当前文件中的任何位置中,所以这种定义方式也是正确的
    printf("N = %d\n", N);
}
int main(int argc, char const *argv[])
{
    test06();
    return 0;
}

在这里插入图片描述

4、带参数的宏

#include <stdio.h>
#define MY(a, b) a *b
void test00()
{
    printf("MY(a,b) = %d\n", MY(2, 3)); // 使用 10*20代替 MY(2, 3)
}
int main()
{
    test00();
}

在这里插入图片描述
使用 gcc -E 01_code.c -o 01.i进行预编译在这里插入图片描述
在这里插入图片描述

注意事项:

(1)、宏定义的时候不能有数据类型
在这里插入图片描述
(2)、宏定义不能保证参数的完整性

#include <stdio.h>
#define MY(a, b) a *b
#define MY_1(a, b) a *b
#define MY_2(a, b) ((a) * (b))
#define MY_3(a, b) (a) * (b)
void test00()
{
    printf("MY(a,b) = %d\n", MY(2, 3));             // 使用 a*b代替 MY(2, 3)
    printf("MY_1(a,b) = %d\n", MY_1(2 + 2, 3 + 3)); // 2 + 2 * 3 + 3
    printf("MY_2(a,b) = %d\n", MY_2(2 + 2, 3 + 3)); //((2+2) * (3 + 3))
    printf("MY_3(a,b) = %d\n", MY_3(2 + 2, 3 + 3)); //(2+2) * (3 + 3)
}
int main()
{
    test00();
}

在这里插入图片描述
(3)、宏不能作为 类、结构体的成员

5、带参宏(宏函数)和带参函数的区别

(1)、带参宏调用多少次就会展开多少次,执行代码的时候没有函数的调用过程,不需要压栈和弹栈,所以带参宏是浪费了栈的空间,因为在预编译的时候被多次展开,所以节省时间(典型的使用空间换取时间)
(2)、带参数的函数,只有一段,存储在代码段,所以在编译阶段会进行多次压入栈中、退出栈中,所以节省了空间,但是压栈和退栈浪费了时间(典型的使用时间换取空间)
(3)、带参数的函数中的参数有数据类型定义,但是带参宏中没有数据类型的定义

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/180115.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【c语言进阶】枚举与联合体的基本知识大全

&#x1f680;write in front&#x1f680; &#x1f4dc;所属专栏&#xff1a;c语言学习 &#x1f6f0;️博客主页&#xff1a;睿睿的博客主页 &#x1f6f0;️代码仓库&#xff1a;&#x1f389;VS2022_C语言仓库 &#x1f3a1;您的点赞、关注、收藏、评论&#xff0c;是对我…

1600_Cmake学习笔记_Cmake实践学习

全部学习汇总&#xff1a; GreyZhang/g_cmake: my learning notes for cmake tool. (github.com) 之前考虑过是否要学习Cmake&#xff0c;经过各种对比之后放弃了&#xff0c;我选择了去学习scons。在实际的工作以及学习中scons也的确给了我很大的受益。当时出于各种方面的原因…

PyQt5开发环境搭建 1.1 软件安装

写在前面的话&#xff08;1&#xff09;相对而言&#xff0c;python&#xff0c;PyQt5安装还是比较快的。Qt这个又大又慢。Eric也是需要比较长的时间。&#xff08;2&#xff09;安装失败很正常&#xff0c;多尝试几次&#xff0c;多查查&#xff0c;努力装好软件。安装和配置是…

【Linux】VM与Linux的安装

1.1 VMWare安装 1&#xff09;VMware Workstation Pro安装向导 2&#xff09;VMware Workstation安装的许可协议。 3&#xff09;VMware Workstation安装路径。 4&#xff09;VMware Workstation增强型键盘功能。 5&#xff09;VMware Workstation软件检查更新和帮助完善 6&am…

Linux常见的进程间通信

目录管道pipe匿名管道接口介绍示例代码fifo命名管道接口介绍代码示例匿名管道与命名管道的区别shm共享内存接口介绍相关指令代码示例特点总结信号信号量socket套接字管道 管道是一种较老的&#xff0c;半双工通信方式&#xff0c;即数据只能向一个方向流动&#xff08;即一个进…

力扣 2303. 计算应缴税款总额

题目 给你一个下标从 0 开始的二维整数数组 brackets &#xff0c;其中 brackets[i] [upperi, percenti] &#xff0c;表示第 i 个税级的上限是 upperi &#xff0c;征收的税率为 percenti 。税级按上限 从低到高排序&#xff08;在满足 0 < i < brackets.length 的前提…

spring笔记下(AOP、事务管理)

一、AOP概述 1. AOP介绍 AOP(Aspect Oriented Programming)&#xff1a;面向切面编程&#xff0c;一种编程范式&#xff0c;指导开发者如何组织程序结构&#xff0c;是oop的延续。&#xff08;OOP面向对象编程&#xff09; AOP作用&#xff1a;在不惊动原始设计的基础上为其进…

LeetCode刷题模版:221 - 230

目录 简介221. 最大正方形222. 完全二叉树的节点个数223. 矩形面积224. 基本计算器【未理解】225. 用队列实现栈226. 翻转二叉树227. 基本计算器 II【未理解】228. 汇总区间229. 多数元素 II230. 二叉搜索树中第K小的元素结语简介 Hello! 非常感谢您阅读海轰的文章,倘若文中有…

【学习打卡 Free-Excel 】Task6 查找函数

文章目录1. VLOOKUP用法示例注意情况一情况二2. 通配符用法示例3.XLOOKUP用法匹配类型搜索模式1. VLOOKUP 用法 【VLOOKUP函数】VLOOKUP&#xff08;要查找的值&#xff0c;查找区域&#xff0c;要返回的结果在查找区域的第几列&#xff0c;精确匹配或近似匹配&#xff09;示…

JAVA Web 常见问题解决方案(持续更新,欢迎投稿常见问题)

大家有什么问题未解决的可以试图联系博主&#xff0c;群号在主页的详细资料 都是博主自己学习过程中遇到的问题&#xff0c;大家有什么常见问题欢迎Git 问题集目录 找到适合自己版本的pom依赖 IDEA实体类快速创建 get(),set(),toString()方法 报错Cannot find class: com.mysq…

【图卷积网络】03-空域卷积介绍 (一)

注&#xff1a;本文为3.1-3.2 空域卷积视频笔记&#xff0c;仅供个人学习使用 1、谱域图卷积 1.1 回顾 上篇博客【图卷积神经网络】02-谱域图卷积介绍讲到了三个经典的谱域图卷积&#xff1a; SCNN用可学习的对角矩阵来代替谱域的卷积核。 ChebNet采用Chebyshev多项式代替谱…

webpack使用Ammo.js - 在react中使用Ammo.js

真实麻烦啊[我的项目仓库 Next.js项目 仅供参考](https://gitee.com/honbingitee/three-template-next.js/tree/feature%2Fphysics/)本文展示使用ammo.wasm.js 结合ammo.wasm.wasm的wasm版本使用方法1. 配置webpack2. 导出Ammo 修改ammo.wasm.js文件3. 删除语句 通过查找 this.…

【Flink】详解Flink的八种分区

简介 Flink是一个流处理框架&#xff0c;一个Flink-Job由多个Task/算子构成&#xff0c;逻辑层面构成一个链条&#xff0c;同时Flink支持并行操作&#xff0c;每一个并行度可以理解为一个数据管道称之为SubTask。我们画图来看一下&#xff1a; 数据会在多个算子的SubTask之间相…

【奇妙的数据结构世界】用图像和代码对链表的使用进行透彻学习 | C++

第九章 链表 目录 第九章 链表 ●前言 ●一、链表是什么&#xff1f; 1.简要介绍 2.具体情况 ●二、链表操作的关键代码段 1.类型定义 2.常用操作 ●总结 前言 简单来说&#xff0c;数据结构是一种辅助程序设计并且进行优化的方法论&#xff0c;它不仅讨论数据的存储与处…

打工人必知必会(一)——规章制度保险劳动合同变更

目录 参考 1、规章制度的生效要件 2、工资的发放形式 3、社会保险的基本规定 4、基本养老保险 5、医疗保险、失业保险、工伤保险、生育保险 6、劳动合同的变更 第一节 协商变更劳动合同 第二节 单方变更劳动合同 参考 《HR全程法律顾问&#xff1a;企业人力资源管理高…

5-6中央处理器-多处理器系统硬件多线程

文章目录一.多处理器系统&#xff08;一&#xff09;计算机体系结构分类1.单指令单数据流SISD2.单指令多数据流SIMD3.多指令单数据流MISD4.多指令多数据流MIMD&#xff08;1&#xff09;(共享内存)多处理器系统/多核处理器&#xff08;2&#xff09;多计算机系统&#xff08;二…

逆水寒魔兽老兵服副本攻略及代码分析(英雄武林风云录,后续更新舞阳城、扬州、清明等副本攻略)

文章目录一、武林风云录1&#xff09;老一&#xff1a;陈斩槐&#xff08;只有四个机制&#xff0c;dps压力不大&#xff0c;留爆发打影子就行&#xff09;&#xff08;1&#xff09;点名红色扇形区域&#xff08;2&#xff09;点名红色长条&#xff0c;注意最后还有一段大劈&a…

MongoDB入门(特点,使用场景,命令行操作,SpringData-MongoDB)

今天我们将通过这一篇博客来了解MongoDB的体系结构&#xff0c;命令行操作和在JAVA 当中使用SpringData-MongoDB 来 操作MongoDB。 如果没有安装的小伙伴 可以看一下 这篇文章 (59条消息) 开源的文档型数据库–MongoDB&#xff08;安装&#xff09;_一切总会归于平淡的博客-CS…

LeetCode[128]最长连续序列

难度&#xff1a;中等题目&#xff1a;给定一个未排序的整数数组 nums&#xff0c;找出数字连续的最长序列&#xff08;不要求序列元素在原数组中连续&#xff09;的长度。请你设计并实现时间复杂度为 O(n)的算法解决此问题。示例 1&#xff1a;输入&#xff1a;nums [100,4,2…

java中new的含义如何理解?

在Java中&#xff0c;new关键字被使用来创建一个新的对象&#xff0c;可以理解为创建的意思。使用关键字new来创建一个对象也叫类的实例化&#xff0c;使用new创建对象时&#xff0c;会调用构造方法初始化对象声明对象Cat cat 在栈内存中实例化对象 new Cat(参数); 在堆内存中每…