2023届C/C++软件开发工程师校招面试常问知识点复盘Part 8

news2025/4/16 13:02:47

目录

        • 52、vector<string>是怎么存储的?
        • 53、epoll的底层原理
            • 53.1 对比select和poll
            • 53.2 ET和LT的工作模式
        • 54、进程、线程、协程的理解和他们的通信方式
            • 54.1 进程的含义
            • 54.2 线程的含义
            • 54.3 协程的含义
            • 54.4 进程间通信IPC
            • 54.5 线程间通信方式
        • 55、define宏定义的用法
            • 防止一个头文件被重复包含
            • 求两个数的最大值和最小值
            • 返回数组元素的个数
            • 得到一个变量的地址
            • 从指定的地址获取一个字节或者int
            • 将一个字母转换为大写字母
        • 56、关于数组与指针、数组名的各项细节
            • 数组名本身有数组属性,可以直接对数组名进行`sizeof`求数组大小;赋值之后就不存在了这种属性了
            • 32位机指针的大小是4个字节、64位机指针的大小是8个字节
            • 数组名的用法上更类似于一个`指针常量`,也即指针的指向不能改变,指向数组的首地址
            • 数组的首地址与数组的第一个元素的起始地址是等价的
            • 指针的移动与运算
            • 关于指针数组与`数组指针`
        • 57、编译的具体过程
            • 编译过程具体可分为4步`预处理`—`编译`—`汇编`—`链接`
            • 预处理
            • 编译
            • 汇编
            • 链接

52、vector是怎么存储的?

  • vector底层的数组中存放的string对象的地址
  • 因为需要保证随机访问,但是string本身无法立即确定其大小,所以无法直接存放string对象,而是采取存放地址的方式

53、epoll的底层原理

53.1 对比select和poll

epoll的工作方式非常高效

  1. select和poll是使用线性方式检测socket集合是否需要处理的,而epoll是基于红黑树来管理待检测集合的
  2. select和poll每次都需要线性的扫描整个集合,但是epoll是回调的方式,可以直接获知那些集合有需要响应
  3. select和poll需要对返回的集合进行判断才会知道哪些文件描述符是就绪的,epoll可以直接得到就绪的文件描述符集合
  4. epoll没有最大文件描述符的限制,仅仅受限于系统能打开的文件描述符的限制

三个操作函数

  1. 创建
  2. 添加和维护管理
  3. 检测是否存在有就绪的文件描述符
#include <sys/epoll.h>
// 创建epoll实例,通过一棵红黑树管理待检测集合
int epoll_create(int size);
// 管理红黑树上的文件描述符(添加、修改、删除)
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
// 检测epoll树中是否有就绪的文件描述符
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);

对于int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

// 联合体, 多个变量共用同一块内存        
typedef union epoll_data {
 	void        *ptr;
	int          fd;	// 通常情况下使用这个成员, 和epoll_ctl的第三个参数相同即可
	uint32_t     u32;
	uint64_t     u64;
} epoll_data_t;

struct epoll_event {
	uint32_t     events;      /* Epoll events */
	epoll_data_t data;        /* User data variable */
};
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

// epfd  就是创建的epfd实体
// op    用于指定执行什么管理操作,是删除、添加、还是修改
// fd    用于指定要添加的socket是啥
// event 是一个结构体,用来指定fd相关事件以及一些用户数据,事件的话有EPOLLIN:读事件、EPOLLOUT:写事件、EPOLLERR:异常事件

对于int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);

// epfd    是epoll对象实例
// events  是返回的就绪状态的文件描述符
// maxevents 表示 结构体的容量
// 0-> 不等待  -1-> 一直等待  
53.2 ET和LT的工作模式

LT是指水平触发: 这是默认的工作方式,如果文件描述符需要被响应,相应的事件就会被触发,如果我们不处理,或者没有处理完全,就会继续触发

ET是指边沿触发: 这是比较高校的方式,如果文件描述符需要被响应,相应的事件只会被触发一次,不管我们处理与否

  • 循环接受数据,希望能够一次处理完全
  • 因此需要使用非阻塞的函数,收发数据,特别是接受

54、进程、线程、协程的理解和他们的通信方式

进程、线程、协程的理解和他们的通信方式

54.1 进程的含义
  • 进程是操作系统进行资源分配的基本单位;它可以申请和拥有系统资源,是一个动态的概念
  • 进程拥有自己的地址空间,也即拥有自己独立的内存空间,不同的进程之间需要IPC也即进程间通信(管道、信号、消息队列、共享内存、信号量、Socket);
  • 由于每一个进程都拥有属于自己的系统资源,因此上下文切换开销(栈、寄存器、虚拟内存、文件句柄等)比较大;进程切换由操作系统完成。
54.2 线程的含义
  • 线程是进程的一个执行实体,是CPU调度的基本单位;线程自己基本上不拥有系统资源,只拥有一些在运行中必不可少的资源(PC、寄存器、栈)
  • 同属于一个进程的线程共享进程所拥有的全部资源; 线程之间的通向主要靠共享内存、全局变量等
  • 相比进程线程的切换只需要保存和恢复PC、寄存器、栈,因此开销较小;线程的切换由操作系统完成。
54.3 协程的含义
  • 协程是一种用户态轻量级线程,协程的调度完全由用户控制,不需要进入内核态;
  • 协程拥有的资源更少,有自己的寄存器和栈,协程切换只需要保护好这些资源即可,协程的上下文切换开销最小,速度最快
  • 协程可以不加锁的访问全局变量因为协程的调度由用户控制,不会出现读写竞争,因此可以不加锁———我自己的理解)
54.4 进程间通信IPC

https://www.cnblogs.com/zhuminghui/p/15405591.html

  1. 进程间的通信要经过内核

  2. 常用的IPC方式有:管道、消息队列、共享内存、信号量、信号、socket等

  • 为什么需要通信呢?

    • 因为不同的进程之间地址空间是独立的,如果需要协作,则就需要特殊的方式进行通信也即IPC通信

54.4.1、管道(pipe)

匿名管道是半双工的、单向的、如果需要相互通信,就需要创建两个管道,并且只能在由亲缘关系的进程间使用。亲缘关系如父子进程。

有名管道也是半双工的、单向的,但是可以允许无亲缘关系的进程之间通信

缺点:管道通信方式效率低,不适合进程间频繁地交换数据。

54.4.2、消息队列

消息队列是保存在内核中的消息链表,所以消息队列的生命周期是跟随内核与操作系统的。

消息体用户自定义的数据类型,消息的发送方和接受方必须约定好消息体的数据类型,因此每个消息体都是有固定格式和大小的存储块。

  • 两个进程之间通信就像发邮件,你来一封,我回一封

  • 优点:解决了信号传递信息少、管道只能曾在无格式的字节流以及缓冲区大小有限的缺点;

  • 缺点:通信不及时,消息体大小有限制、会发生用户态和内核态之间的频繁拷贝过程

54.4.3、共享内存

共享内存是两个进程都能访问到的一块内存空间,因此如果一个进程写入了数据,另一个进程立即就能看到。因此效率非常高,也是所有的IPC中最快的一种

54.4.4、信号量

信号量主要是用于和共享内存进行合作,保证共享资源的互斥与同步,用于防止数据访问的冲突与覆盖问题

54.4.5、信号

Linux内部定义了几十种信号,分别代表不同的意义。可以在任何时候发送一个信号给进程,用来告诉某个进程某事件发生

  • 信号来源主要是硬件来源软件来源

  • 当一个进程收到一个信号后,一般有三种处理方式

    1. 执行Linux给每一个信号提供的默认操作
    2. 捕捉信号,执行我们自己定义的处理函数
    3. 忽略不处理

54.4.6、Socket

可以用于不同设备上不同进程间的通信。

54.5 线程间通信方式

线程通信的主要目的是线程同步,所以没有像进程中用于交换数据的通信机制

主要是锁机制,如互斥锁、读写锁、条件变量、信号量

55、define宏定义的用法

define宏定义的用法

  1. 防止一个头文件被重复包含
    #ifndef HEAD_H
    #define HEAD_H
    // 头文件内容
    
    #endif
    
  2. 求两个数的最大值和最小值

    本质就是用一句话、一行代码、一个表达式实现该宏的功能,并且该表达式的结果就是宏的目标

    #define MAX(x, y) ((x) > (y) ? (x) : (y))
    #define MIN(x, y) ((x) > (y) ? (y) : (x))
    // 宏函数的调用
    cout << MAX(10, 100) << endl; // 100
    
  3. 返回数组元素的个数
    #define ARR_SIZE(arr) (sizeof((arr)) / sizeof((arr[0])))
    
    // 调用
    int arr[15] = {0};
    cout << ARR_SIZE(arr) << endl; // 15
    
  4. 得到一个变量的地址
    #define GET_PTR(var) ((void *)&(var))
    
    // 调用
    double d = 100.11;
    cout << GET_PTR(d) << endl; // 0x72fdc8
    
  5. 从指定的地址获取一个字节或者int
    #define MEM_B(ptr) (*((char *)(ptr)))  // 获取一个字节
    #define MEM_INT(ptr) (*((int *)(ptr))) // 从一块地址上去一个int
    
  6. 将一个字母转换为大写字母
    #define UPCASE(c) (((c) <= ('z') && (c) >= ('a')) ? ((char)((c) - ('a') + ('A'))) : (c))
    
    cout << UPCASE('a') << endl; // A
    cout << UPCASE('A') << endl; // A
    

56、关于数组与指针、数组名的各项细节

  1. 数组名本身有数组属性,可以直接对数组名进行sizeof求数组大小;赋值之后就不存在了这种属性了
    // 数组名本身有数组属性
    int arr[15] = {0};
    cout << size(arr) << endl; // 60
    
    // 如果将数组名传递到函数中就不带有数组属性了,将退化为一个指针
    cout << func1(arr) << endl;  // 如果调用下面的函数,就会丧失数组属性
    
    int func1(int arrp[])
    {
        return sizeof(arrp);  // 退化为指针后,sizeof得到的仅仅是指针大小
    }
    
  2. 32位机指针的大小是4个字节、64位机指针的大小是8个字节
  3. 数组名的用法上更类似于一个指针常量,也即指针的指向不能改变,指向数组的首地址
    int arr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    arr++;  // 不合法---->因为数组名arr是一个指针常量,自身是不可以改变的
    int a =  *(arr + 1);    // 等价于arr[1];
    
    int* ptr = arr; 		//通过赋值操作,用一个普通的指针指向了数组arr的首地址
    ptr++;	// 合法
    ++ptr;	// 合法
    
    int* ptr2 = &arr[0];  	// 等价于 int* ptr = arr; 结果都是使得一个普通指针指向了数组的首地址
    
  4. 数组的首地址与数组的第一个元素的起始地址是等价的
    int arr[3] = {1, 2, 3};
    // arr指向数组的首地址
    // &arr[0]指向数组第一个元素的起始地址
    // 两者是同一个位置
    
  5. 指针的移动与运算
    • 指针和指针只能进行相减运算(得到的是间隔了多少个元素),不能进行乘、除、加等运算

    • 指针只能加上一个常量

      int arr[10] = {0};
      int * p = arr;
      *(p + 9) 指向最后一个元素 等价于 arr[9]
      同样也等价于*(arr + 9)
          
      在编译器中,arr[i]的访问过程就是转化为 *(arr + i)然后访问的
      
  6. 关于指针数组与数组指针
    // 声明一个指针数组,该数组有10个元素,其中每个元素都是一个指向 int 类型对象的指针
    int *arr[10];
    // 声明一个数组指针,该指针指向一个 int 类型的一维数组
    int (*arr)[10];  
    

57、编译的具体过程

编译的具体过程

  1. 编译过程具体可分为4步预处理编译汇编链接
  2. 预处理
    • 展开头文件、展开宏定义、删除注释
    • gcc命令gcc -E ...
    • 生成的中间文件为.i文件,依旧是源代码
  3. 编译
    • .i文件编译成.s文件;也即源代码文件转化为汇编代码
    • gcc命令gcc -S ...
    • 生成的中间文件为.s文件,是汇编代码
    • 主要的编译优化就是发生在这个阶段
  4. 汇编
    • .s文件逐行翻译成.o文件;也即从汇编翻译成二进制机器码
    • gcc命令gcc -c ...
    • 生成的中间文件为.o文件
  5. 链接
    • 这个阶段 GCC 调用链接器对程序需要调用的库以及多个.o文件之间进行链接,生成可执行的二进制文件
    • gcc命令:直接gcc + 源文件 编译即可,不需要其他参数
    • 默认生成a.out文件,也可以使用-o 文件名,自定义生成的文件的名字(该命令也可以用于上述的几个阶段)

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

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

相关文章

【JavaDS】优先级队列(PriorityQueue),堆,Top-k问题

✨博客主页: 心荣~ ✨系列专栏:【Java实现数据结构】 ✨一句短话: 难在坚持,贵在坚持,成在坚持! 文章目录一. 堆1. 堆的概念2. 堆的存储方式3. 堆的创建4. 元素入堆5. 元素出堆6. 获取堆中元素二. 优先级堆列(PriorityQueue)1. 优先级队列2. PriorityQueue的特性3. 集合框架中P…

万字启程——零基础~前端工程师_养成之路001篇

目录 什么是前端 什么是后端 前端和后端的区别 前端工程师职责 后端工程师职责 前端的核心技术 HTML CSS JavaScript RESTful结构 特点 HTTP请求方式有哪些 目前最火的前端框架Vue vue优点 vue的响应式编程、组件化 搭建编程环境 什么是编程环境 前端的编程环…

华为云CDN,海量资源智能路由,让内容传输更快一步

华为云CDN,海量资源智能路由,让内容传输更快一步 云服务对于我们生活的影响已经愈发深入&#xff0c;在数字化转型的大背景下&#xff0c;城市管理、公共交通、医疗健康等领域都需要云服务的支持。华为云作为国内知名的云服务平台&#xff0c;以技术强、更可靠、资源多以及帮肋…

基于CentOS 7.9操作系统应用httpd配置本地镜像(本地yum源)

记录&#xff1a;301 场景&#xff1a;配置离线本地镜像源(本地yum源)的三种方式&#xff1a;直接使用iso镜像包配置、使用httpd服务应用iso镜像包配置、使用httpd服务应用rpm包配置。在内网环境或者局域网环境&#xff0c;基于CentOS 7.9操作系统应用httpd配置本地镜像(本地y…

手把手带你玩转Spark机器学习-深度学习在Spark上的应用

系列文章目录 手把手带你玩转Spark机器学习-专栏介绍手把手带你玩转Spark机器学习-问题汇总手把手带你玩转Spark机器学习-Spark的安装及使用手把手带你玩转Spark机器学习-使用Spark进行数据处理和数据转换手把手带你玩转Spark机器学习-使用Spark构建分类模型手把手带你玩转Spa…

Python学习笔记(十三)——编译错误和异常处理

异常和异常类 Python常见错误 语法错误 源代码存在拼写语法错 误&#xff0c;这些错误导致Python 编译器无法把Python源代 码转换为字节码&#xff0c;故也称 之为编译错误。>>> print("我爱山大"} SyntaxError: invalid syntax 运行时错误 • 程序中没有…

Python常用库1:collections,容器数据类型

collections&#xff1a;数据容器 点这里跳到原文地址。预计阅读时长&#xff1a;10分钟未完待续&#xff0c;遇到相关力扣题目&#xff0c;会继续补充~ 文章目录前言一、Collections中的内置函数二、各个函数的使用1. deque1.1 deque的介绍1.2 deque支持的方法1.3 使用deque解…

js-键盘事件

onkeydown:按键被按下 onkeyup:按键被松开 事件绑定的对象&#xff1a;键盘事件一般绑定给可以获取焦点的对象或者document对象 焦点&#xff1a;光标在闪的&#xff1a;比如input标签 如果一直按按键不松手&#xff0c;按键会一直被触发 当&#xff1a;onkeydown连续触发时…

THREE.JS实现看房自由(VR看房)

VR看房一、前言二、基础知识三、场景3.1 网络模型3.2 光照3.2.1 环境光3.2.2 平行光3.2.3 点光源3.2.4 聚光灯3.2.5 半球光四、相机4.1 正交相机4.2 透视相机五、渲染器六、贴图纹理6.1 基础介绍6.2 环境贴图6.3 HDR处理七、拓展7.1 坐标系7.2 控制器7.3 自适应7.4 全屏响应7.5…

C#基础·补丁

文章目录一 命名空间二字符串2.1 System.String类2.2 StringBuilder类三 正则表达式3.1 什么是正则表达式&#xff1f;3.2 查找举例3.3 重复描述字符举例3.4 反义字符3.5 基本语法元字符3.6 定位元字符3.7 择一匹配3.8 分组一 命名空间 二字符串 字符串类 System.String(strin…

python数据分析之numpy

数据分析之Numpy 1、Numpy的数组对象及其索引 import numpy as npimport numpy as npanp.array([1,2,3,4]) print(a) bnp.array([2,3,4,5]) print(b)print(ab)产生数组 从列表产生数组&#xff1a; list_array[1,2,3,4] anp.array(list_array) print(a)从列表传入&#xff…

PCB设计很简单?生产问题才是考验工程师能力的标准!

BOM清单有误 SMT产线&#xff1a;物料封装怎么和PCB焊盘不一致呢&#xff1f;停线排查。 仓库&#xff1a;我是按照BOM清单发的物料。 硬件研发&#xff1a;哎&#xff0c;BOM整理时马虎了。 过孔焊盘问题 “ 连锡问题 产线维修&#xff1a;怎么这么多连锡导致不良的产品&…

【安信可NB-IoT模组EC系列应用笔记⑧】用NB-IoT模组EC系列了解LwM2M协议并接入云平台

文章目录前言一、测试准备1、硬件准备2、云平台准备二、云平台连接1.注册入网2.读取IMSI及IMEI3.利用IMSI及IMEI创建设备4.LwM2M连接云平台设备三、 数据互交1.ATMIPLNOTIFY 通知属性变化2.ATMIPLREADRSP 返回读取结果3.ATMIPLWRITERSP 发送写入结果4.ATMIPLEXECUTERSP 发送执行…

1.uniapp全局状态管理

概念&#xff1a;把多个组件之间共享数据抽离出来&#xff0c;通过一个“单例模式”进行管理 工具&#xff1a;具备全局状态管理的库 Vuex:全局状态管理中的库 步骤&#xff1a; 1.建立Store文件夹 2.建立index.js文件 3.在main.js中注册Vue插件 4.测试Vuex是否导入成功 …

面试面麻了,别再为难软件测试人员了···

前言 有不少技术友在测试群里讨论&#xff0c;近期的面试越来越难了&#xff0c;要背的八股文越来越多了,考察得越来越细&#xff0c;越来越底层&#xff0c;明摆着就是想让我们徒手造航母嘛&#xff01;实在是太为难我们这些测试工程师了。 这不&#xff0c;为了帮大家节约时…

基于单片机的双足仿生运动机器人的设计

目录 1 概述 1 1.1 研究背景及意义 1 1.2 机器人的应用领域及发展现状 1 1.2.1 应用领域 1 1.2.2 发展现状 1 1.3 双足机器人设计要求 2 1.3.1 硬件部分 2 1.3.2 软件部分 2 2 系统方案设计 3 2.1 主控芯片选择 3 2.2 机器人自由度选择 3 2.3 驱动方案选择 3 2.4 双足机器人的步…

00后表示真干不过,部门新来的00后测试员已把我卷崩溃,想离职了...

在程序员职场上&#xff0c;什么样的人最让人反感呢? 是技术不好的人吗?并不是。技术不好的同事&#xff0c;我们可以帮他。 是技术太强的人吗?也不是。技术很强的同事&#xff0c;可遇不可求&#xff0c;向他学习还来不及呢。 真正让人反感的&#xff0c;是技术平平&#x…

web安全之信息收集

&#x1f4aa;&#x1f4aa; web安全之信息收集1.网络入口/信息1.1网络拓扑信息1.2 IP信息1.3线下网络2.域名信息2.1Whios2.2搜索引擎搜索2.3. 第三方查询2.4. ASN信息关联2.5. 域名相关性2.6. 网站信息利用2.7. HTTPS证书2.8. CDN2.9. 子域爆破3.端口信息3.1常见端口3.2端口扫…

具有现代设计和最新Bootstrap版本的数字市场HTML模板

DegMark是具有现代设计和最新Bootstrap版本的数字市场HTML模板。凭借优秀的设计很容易创建虚拟商品交易网站&#xff0c;比如图片素材在线交易&#xff0c;视频文件交易&#xff0c;代码交易等虚拟商品交易。 主要特色 Bootstrapv5 移动响应 FontAwesome图标 jQuery增强 …

metaRTC Visual Studio编译指南

概述 metaRTC windows版本提供qt和vs2019两种编译支持&#xff0c;vs2019编译工程支持从metaRTC6.0版本开始&#xff0c;qt编译在B站有视频教程。 metaRTC5 windows版编译教程_哔哩哔哩_bilibilimetartc5编译教程&#xff0c;windows版本只支持msvc,下载所带第三方库为msvc20…