C/C++八股文整理

C/C++

  • 指针

    指针p,pointer,也叫地址,就是内存块的首地址
    指针变量
    1、存放指针数据的变量
    2、int*p;//p只能存放int类型内存块的地址
    3、32位环境下,所有指针变量都是4字节。64位环境下是8字节
    4、未赋初值的指针指针变量禁止使用。(直接崩溃)
    指针常用含义
    *p的含义:p指针指向的地址里存放的数据
    p+n的含义:p地址向后偏移n个存储单元,得到的新地址
    p[n]的含义:表示p地址第n+1个内存块

  • 数组

    1、数组是数目固定,类型相同,连续存放的一组有序数的集合
    2、C语言规定,数组名就是内存块的首地址,他是一个常量指针
    3、定义数组时长度不能使用变量
    4、a+n和a[n]的区别
    5、数组中每个元素都是变量
    6、数组部分元素赋初值,其余未赋值元素均为0;所有元素都不赋值,数组元素均为乱值。

  • 数组和链表的区别

    链表:逻辑上相邻的元素在物理位置上不一定相邻。
    优点: 插入、删除效率高,不需要一个连续的很大的内存
    缺点: 查找某一个位置的元素效率低
    数组
    优点: 存取速度快
    缺点:
    1.整块连续空间,占很大内存。
    2.插入或删除数据效率低、不方便

  • 数组和指针的区别

    1、数组是一中数据结构,指针是一个地址
    2、sizeof测量字节大小

  • 数组指针和指针数组

    数组指针:是指针,是指向数组的指针。这个指针存放着一个数组的首地址
    char (*p)[10]
    指针数组:是数组,是元素为指针的数组 。这个数组的所有元素都是指针类型
    char *(p[10])

  • 内存管理

  • 内存五大分区

    五大内存分区(笔记)
    在这里插入图片描述
    1、堆区(heap) — 允许程序在运行时动态地申请某个大小的内存空间, 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两回事。
    2、栈区(stack) — 由编译器自动分配释放,存放函数的参数值,局部变量的值等。
    3、全局区(静态区) — 全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域,程序结束后由系统释放。
    4、文字常量区 — 常量字符串就是放在这里的,只读的。程序结束后由系统释放。
    5、程序代码区 — 存放程序的编译后的可执行二进制代码,CPU执行的机器指令,并且是只读的。
    在这里插入图片描述
    栈和堆的对比
    在这里插入图片描述

  • 大小端存储

    大端存储是将数据的高位存储在内存的低地址处(第一个字节就是高位,很容易判断正负性)
    小端存储是将数据的低位存储在内存的低地址处(第一个字节是低位,最后一个字节是高位,可以依次取出相应的字节进行运算,并且最终会把符号位刷新,这样运算起来更高效)在这里插入图片描述
    什么是大小端?怎么分辨大小端?

  • 运算符优先级

    口诀:单目算术位关系,逻辑三目后赋值
    C语言运算符优先级(超详细)

  • sizeof关键字和strlen函数的区别

sizeofstrlen
能测试常量,变量,数组、类型 所占 应占的内存大小的单位字节数只能测量字符串 计算字符串 str 的实际长度,直到空结束字符,但不包括空结束字符
在编译时就计算出了sizeof的结果在运行时才能计算出来

sizeof:
测试字符串 就是字符个数 + 1
测试变量 就是变量对照类型分配的空间大小
测试数组 就是数组所占的空间大小,元素占的空间 * 数组长度
所有指针变量 所占4字节(32 系统)

  • strcpy函数和memcpy函数的区别

    1、可复制内容不同:strcpy只能用于字符串复制;memcpy可以复制任何内容,如字符数组,结构体,类等。
    2、复制方法不同:strcpy不需要指定长度,遇到"\0"结束符才会结束,如果空间不够,就会引起内存溢出;memcpy则需要在第三个参数指定长度
    3、用途不同:通常复制字符串使用strcpy,其余情况则使用memcpy,但如果字符串中含有"\0"则使用memcpy

[解释]内存溢出、内存泄漏(内存泄漏会引起内存溢出)
内存泄漏:站着茅坑不拉屎)申请的内存空间没有被正确释放,导致后续程序里这块内存被占用,而且指向这块内存空间的指针又不存在时,这块内存也就永远不可达了,内存空间就这么一点点被蚕食。
内存溢出: 用户实际的数据长度超过了申请的内存空间大小,导致覆盖了其他正常数据,容易造成程序异常。

  • strcat、strncat、strcmp、strcpy哪些函数会导致内存溢出?如何改进?

    strcpy函数会导致内存溢出。
    1、strcat()函数主要用来将两个char类型连接。
    2、strncat()主要功能是在字符串的结尾追加n个字符。
    3、strcmp(str1,str2),是比较函数,若str1=str2,则返回零;若str1<str2,则返回负数;若str1>str2,则返回正数。(比较字符串)
    4、strcpy拷贝函数不安全,他不做任何的检查措施,也不判断拷贝大小,不判断目的地址内存是否够用。
    5、strncpy拷贝函数,虽然计算了复制的大小,但是也不安全,没有检查目标的边界。
    6、strncpy_s是安全的。

  • extern关键字和static关键字的区别

    static:
    1、用于局部变量:表示该局部变量是私有的,其存储位置由栈区变成静态区;生命周期延长,在函数执行完毕后并不会被销毁,整个程序执行完成后才会销毁。
    2、用于全局变量:表示该全局变量是私有的,其外部链接属性变为内部链接属性,只能在本文件中使用,不能通过extern引用。
    3、用于函数:表示该函数是私有的,其外部链接属性变为内部链接属性,只能在本文件中使用,不能通过extern关键字对其引用。

    extern:
    1、用于本文件:定义在下方的全局变量需要在定义的上方使用时,需要通过extern引用。
    2、用于其他文件:定义在其他文件的全局变量想要在本文件使用时,若该变量未被static修饰时,可通过extern关键字在本文件对其声明。

  • extern"C"

    1、在C++使用C的已编译好的函数模块
    2、extern在链接阶段起作用(四大阶段:预处理–编译–汇编–链接)

  • const关键字和define的区别

1、编译器处理阶段不同:const在编译时确定其值;define在预处理阶段进行替换
2、类型检查:const有数据类型,编译时会进行类型检查;define五类型,不进行类型检查
3、内存空间:const 在静态存储区中分配空间,在程序运行过程中内存中只有一个拷贝;define 不分配内存,给出的是立即数,有多少次使用就进行多少次替换,在内存中会有多个拷贝,消耗内存大
4、其他:宏只作替换,不做计算,不做表达式求解
const比define安全

  • malloc和new的区别

    1、特性:malloc/free是C的库函数,需要引入头文件stdlib.h;new/delete是C++的关键字,需要编译器支持。
    2、参数:malloc在申请内存分配时需要显式的指出内存大小;new在申请内存分配时无须指定内存块的大小,编译器会根据类型自行计算。
    3、返回类型:malloc内存分配成功时会返回void*,需要强制类型转换成需要的类型;new内存分配成功时会返回对应类型的指针,无需进行转换。
    4、分配失败:malloc分配失败返回NULL;new分配失败抛出异常。

408

  • TCP 三次挥手四次握手

    三次挥手
    请添加图片描述
    A:是B吗?我要跟你通信,听得到我说话吗?
    B:可以通信,你听得到我说话吗?
    A:我也听得到。

    0、初始,客户端处于INIT状态,服务端处于LISTEN状态(监听状态)
    1、客户端向服务端发送连接请求报文SYN包,同时客户端进入SYN_SEND状态(同步已发送状态),服务端接受到SYN包后进入SYN_RCVD状态(同步收到状态)
    2、服务端向客户端发送SYN+ACK包,,客户端接收到服务端的确认报文后进入ESTABLISHED状态(已建立连接状态)
    3、客户端向服务端发送ACK包表示自己进入已建立连接状态,服务端接收到报文后进入ESTABLISHED状态(已建立连接状态)
    自此连接建立成功

    四次挥手
    请添加图片描述
    A:困了,在干嘛?
    B:在刷视频。
    B:你要睡了吗?
    A:对,晚安。(等她看到消息安心入睡)

    0、初始,客户端处于ESTABLISHED状态,服务端也处于ESTABLISHED状态
    1、客户端向服务端发送连接释放请求报文FIN包,并停止发送数据,且进入FIN_WAIT_1状态(终止等待1状态)
    2、服务端接收到FIN包后向客户端发送确认报文ACK包,并进入CLOSE-WAIT状态(关闭等待状态)
    3、客户端接收到确认报文之后进入FIN_WAIT_2状态(终止等待2状态),等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)
    4、服务器将最后的数据发送完毕之后,向客户端发送连接释放报文FIN包,由于在半关闭状态,服务器很可能又发送了一些数据,此时,服务器就进入了LAST_ACK状态(最后确认状态),等待客户端的确认
    5、客户端接收到连接释放报文后,向服务端发出确认ACK包,客户端就进入了TIME-WAIT(时间等待)状态,【为什么要等待,为了确认服务端接收到了ACK包,否则服务端就一直处于LAST_ACK状态,如果一段时间服务端没有接收到ACK包就会重新发送FIN包重新获取ACK包】注意此时TCP连接还没有释放,必须经过2*MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。
    问题
    1、为什么是三次握手而不是两次
    为了防止已失效的请求报文突然又传到服务器引起错误,保证传输的可靠性,只握手两次的话,如果客户端发送连接请求SYN包后,由于某些原因服务端暂时未能接收到,那么客户端就是再次发送SYN包,然后服务端接收到SYN包后向客户端发送确认连接报文,但此时第一次发送的SYN包传到了服务端,就再次建立了一次连接,而这样服务端就以为是两次连接,而客户端以为是一次连接。
    2、为什么是四次挥手而不是三次
    服务端要确保客户端接收到了自己发送的释放连接请求。
    TCP-B站视频
    TCP协议详解 (史上最全)

  • TCP和UDP

    定义

    TCP—传输控制协议,是面向连接,可靠的字节流服务,当交换数据前须建立TCP连接。
    UDP—用户数据报协议,UDP不提供可靠性,只负责发送,不保证到达。

    区别

    1)TCP是面向连接的,UDP是面向无连接的
    2)UDP程序结构较简单
    3)TCP是面向字节流的,UDP是基于数据报的
    4)TCP保证数据正确性,UDP可能丢包
    5)TCP保证数据顺序到达,UDP不保证

    优缺点

    TCP优点:可靠稳定
    TCP缺点:速度慢,效率低,占用系统资源高,易被攻击
    UDP优点:速度快,比TCP稍安全
    UDP缺点:不可靠,不稳定

    适用场景

    TCP适用于对传输
    UDP:对网络通讯质量要求不高时,要求网络通讯速度要快的场景。

    问题

    1、TCP为什么是可靠连接?
    因为tcp传输的数据满足3大条件,不丢失,不重复,按顺序到达。

  • OSI典型网络模型

    1、物理层:外接设备的介质(网卡 网线 光纤等)
    2、数据链路层:建立逻辑链接 进行硬件物理地址寻址(MAC)差错校检(交换机 网卡)
    3、网络层:进行逻辑地址寻址 实现不同网咯网络之间路径选择(路由器 ip地址)
    4、传输层:定义传输数据的协议端口号(TCP UDP)以及流控和差错校验(防火墙 端到端)
    5、会话层:建立 管理 中止会话(例如:QQ 微信)
    6、表示层:数据表示 安全 压缩
    7、应用层:网络服务与最终用户的一个接口(用户可以操作的界面)

  • 进程和线程

    定义

    进程:是资源分配的基本单位
    线程:是CPU调度的基本单位
    协程:是一种比线程更加轻量级的存在,协程不是被操作系统内核所管理,而完全是由程序所控制(也就是在用户态执行)

    区别

    1)地址空间:线程是进程内的一个执行单元,进程内至少有一个线程,它们共享进程的地址空间,而进程有自己独立的地址空间
    2)资源拥有:进程是资源分配和拥有的单位,同一个进程内的线程共享进程的资源
    3)定义
    4)二者均可并发执行。同一时间内,如果CPU是单核的,则只有一个进程在执行,所谓的并发执行也就是顺序执行,只不过是由于切换速度过快,让人觉得这些进程是在同步执行;多核CPU可以同一时间点有多个进程在执行。
    5)每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口,但线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

    优缺点

    **说明:**一个进程由进程控制块、数据段、代码段组成,进程本身不可以运行程序,而是像一个容器一样,先创建出一个主线程,分配给主线程一定的系统资源,这时候就可以在主线程开始实现各种功能。当我们需要实现更复杂的功能时,可以在主线程里创建多个子线程,多个线程在同一个进程里,利用这个进程所拥有的系统资源合作完成某些功能。
    优缺点:
    1)一个进程死了不影响其他进程,一个线程崩溃很可能影响到它本身所处的整个进程。
    2)创建多进程的系统花销大于创建多线程。
    3)多进程通讯因为需要跨越进程边界,不适合大量数据的传送,适合小数据或者密集数据的传送。多线程无需跨越进程边界,适合各线程间大量数据的传送。并且多线程可以共享同一进程里的共享内存和变量。

    什么时候用进程,什么时候用线程

    1)创建和销毁较频繁使用线程,因为创建进程花销大。
    2)需要大量数据传送使用线程,因为多线程切换速度快,不需要跨越进程边界。
    3)安全稳定选进程;快速频繁选线程;

    多进程、多线程同步(通讯)的方法

    进程间通讯:
    (1)有名管道/无名管道(2)信号(3)共享内存(4)消息队列(5)信号量(6)socket
    线程通讯(锁)
    (1)信号量(2)读写锁(3)条件变量(4)互斥锁(5)自旋锁

    进程线程的状态转换图

    1)就绪状态:进程已获得除CPU外的所有必要资源,只等待CPU时的状态。一个系统会将多个处于就绪状态的进程排成一个就绪队列。
    2)执行状态:进程已获CPU,正在执行。单处理机系统中,处于执行状态的进程只一个;多处理机系统中,有多个处于执行状态的进程。
    3)阻塞状态:正在执行的进程由于某种原因而暂时无法继续执行,便放弃处理机而处于暂停状态,即进程执行受阻。(这种状态又称等待状态或封锁状态)
    【通常导致进程阻塞的典型事件有:请求I/O,申请缓冲空间等。一般,将处于阻塞状态的进程排成一个队列,有的系统还根据阻塞原因不同把这些阻塞集成排成多个队列。】
    在这里插入图片描述

    父进程、子进程

    子进程是父进程的复制品。父进程调用fork()以后,克隆出一个子进程,子进程和父进程拥有相同内容的代码段、数据段和用户堆栈。父进程和子进程谁先执行不一定,看CPU。所以我们一般我们会设置父进程等待子进程执行完毕。
    详细解释
    fork()系统调用,再执行 exec(B)系统调用
    父进程和子进程先后执行的问题:在fork之后,是父进程先执行,然后一个时间片到达之后就是子进程再执行了。

    什么是上下文切换

    进程上下文:一个进程在执行的时候,CPU的所有寄存器中的值、进程的状态以及堆栈中的内容,当内核需要切换到另一个进程时,它需要保存当前进程的所有状态,即保存当前进程的进程上下文,以便再次执行该进程时,能够恢复切换时的状态,继续执行。
    中断上下文:由于触发信号,导致CPU中断当前进程,转而去执行另外的程序。那么当前进程的所有资源要保存,比如堆栈和指针。保存过后转而去执行中断处理程序,快读执行完毕返回,返回后恢复上一个进程的资源,继续执行。这就是中断的上下文。

参考文章

(只是我自己要背的,每次文章切换来切换去很麻烦,就整理了一下)

  • 5
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值