C/C++八股文整理

04-10 1741阅读

目录

  • C/C++
    • 指针
    • 数组
    • 数组和链表的区别
    • 数组和指针的区别
    • 数组指针和指针数组
    • 内存管理
    • 内存五大分区
    • 大小端存储
    • 运算符优先级
    • sizeof关键字和strlen函数的区别
    • strcpy函数和memcpy函数的区别
    • strcat、strncat、strcmp、strcpy哪些函数会导致内存溢出?如何改进?
    • extern关键字和static关键字的区别
    • extern"C"
    • const关键字和define的区别
    • malloc和new的区别
    • 408
      • TCP 三次挥手四次握手
      • TCP和UDP
        • 定义
        • 区别
        • 优缺点
        • 适用场景
        • 问题
        • OSI典型网络模型
        • 进程和线程
          • 定义
          • 区别
          • 优缺点
          • 什么时候用进程,什么时候用线程
          • 多进程、多线程同步(通讯)的方法
          • 进程线程的状态转换图
          • 父进程、子进程
          • 什么是上下文切换

            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])

            • 内存管理

            • 内存五大分区

              五大内存分区(笔记)

              C/C++八股文整理

              1、堆区(heap) — 允许程序在运行时动态地申请某个大小的内存空间, 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两回事。

              2、栈区(stack) — 由编译器自动分配释放,存放函数的参数值,局部变量的值等。

              3、全局区(静态区) — 全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域,程序结束后由系统释放。

              4、文字常量区 — 常量字符串就是放在这里的,只读的。程序结束后由系统释放。

              5、程序代码区 — 存放程序的编译后的可执行二进制代码,CPU执行的机器指令,并且是只读的。

              C/C++八股文整理

              栈和堆的对比

              C/C++八股文整理

            • 大小端存储

              大端存储是将数据的高位存储在内存的低地址处(第一个字节就是高位,很容易判断正负性)

              小端存储是将数据的低位存储在内存的低地址处(第一个字节是低位,最后一个字节是高位,可以依次取出相应的字节进行运算,并且最终会把符号位刷新,这样运算起来更高效)C/C++八股文整理

              什么是大小端?怎么分辨大小端?

            • 运算符优先级

              口诀:单目算术位关系,逻辑三目后赋值

              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,则返回零;若str1str2,则返回正数。(比较字符串)

                  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 三次挥手四次握手

                      三次挥手

                      C/C++八股文整理

                      A:是B吗?我要跟你通信,听得到我说话吗?

                      B:可以通信,你听得到我说话吗?

                      A:我也听得到。

                      0、初始,客户端处于INIT状态,服务端处于LISTEN状态(监听状态)

                      1、客户端向服务端发送连接请求报文SYN包,同时客户端进入SYN_SEND状态(同步已发送状态),服务端接受到SYN包后进入SYN_RCVD状态(同步收到状态)

                      2、服务端向客户端发送SYN+ACK包,,客户端接收到服务端的确认报文后进入ESTABLISHED状态(已建立连接状态)

                      3、客户端向服务端发送ACK包表示自己进入已建立连接状态,服务端接收到报文后进入ESTABLISHED状态(已建立连接状态)

                      自此连接建立成功

                      四次挥手

                      C/C++八股文整理

                      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,申请缓冲空间等。一般,将处于阻塞状态的进程排成一个队列,有的系统还根据阻塞原因不同把这些阻塞集成排成多个队列。】

                      C/C++八股文整理

                      父进程、子进程

                      子进程是父进程的复制品。父进程调用fork()以后,克隆出一个子进程,子进程和父进程拥有相同内容的代码段、数据段和用户堆栈。父进程和子进程谁先执行不一定,看CPU。所以我们一般我们会设置父进程等待子进程执行完毕。

                      详细解释

                      fork()系统调用,再执行 exec(B)系统调用

                      父进程和子进程先后执行的问题:在fork之后,是父进程先执行,然后一个时间片到达之后就是子进程再执行了。

                      什么是上下文切换

                      进程上下文:一个进程在执行的时候,CPU的所有寄存器中的值、进程的状态以及堆栈中的内容,当内核需要切换到另一个进程时,它需要保存当前进程的所有状态,即保存当前进程的进程上下文,以便再次执行该进程时,能够恢复切换时的状态,继续执行。

                      中断上下文:由于触发信号,导致CPU中断当前进程,转而去执行另外的程序。那么当前进程的所有资源要保存,比如堆栈和指针。保存过后转而去执行中断处理程序,快读执行完毕返回,返回后恢复上一个进程的资源,继续执行。这就是中断的上下文。

                      参考文章

                      • C/C++面试高频知识点八股文
                      • 五大内存分区(笔记)
                      • 嵌入式笔试面试题目系列(汇总)
                      • 父进程、子进程
                      • 五大内存分区(笔记)

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

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]