Discuz! Board

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 818|回复: 0

面试问题

[复制链接]

1214

主题

1975

帖子

7486

积分

认证用户组

Rank: 5Rank: 5

积分
7486
发表于 2023-2-14 11:26:46 | 显示全部楼层 |阅读模式
本帖最后由 Qter 于 2023-2-14 13:38 编辑

1.什么是回调函数?
回调函数就是一个通过'函数指针调用'的函数。所以当'一个函数作为参数'使用的时候,这个函数就是回调函数

2.结构体与共用体(联合体)的区别
首先结构体与共用体都是'构造类型',它们的'成员变量'都可以定义为'不同类型'的。
结构体可以同时存储多种变量类型,而共同体同一个时间只能存储和使用多个变量类型的一种,当另一时间,变量类型被改变后,原来的变量类型和值将被舍弃。
共用体的作用是同一个数据项可以使用多种格式,可以节省空间。'所有成员共享一块内存空间',每个成员的'首地址相同'
'结构体的大小'是根据每个成员变量的大小的总量确定的,而'共用体的大小'是根据最大的成员变量的大小确定的

3. static、const、volatile关键字有什么作用?
static:静止、静态
1.修饰全局变量:变量只在本模块内可见,'限定作用域',限制'变量只能在本文件'(当前.c)中使用
        在定义不需要与其他文件共享的全局变量时,加上static关键字能够有效地降低程序模块之间的耦合,避免不同文件同名变量的冲突,且不会误使用。
      
2.修饰局部变量:变量在全局数据区分配内存空间,'延长变量的生命周期',到整个程序结束
      
3.修饰函数:函数的使用方式与全局变量类似,在函数的返回类型前加上static,就是静态函数,'限定作用域',限制'该函数只能在本文件'(当前.c)中使用
        静态函数只能在声明它的文件中可见,其他文件不能引用该函数,不同的文件可以使用相同名字的静态函数,互不影响。
const:只读
C编译器中:被const修饰的变量�'只读变量',本质还是变量,
        有人称其为常变量,和普通变量的区别在于常变量不能用于左值,其余的用法和普通常量一样。
C++编译器中:被const修饰的变量,变量名和初始值会直接放到符号表中,当使用变量名的时候会直接从符号表中读取其值。相较于C编译器,在C++编译器中const修饰的变量更像是常量。
//const 修饰谁 谁不能变----- 修饰 *p 值不能变,但是指向 可以改变
// ----- 修饰 p p的指向不能变 但是 *p的值 可以改变
const int *p; //值不能变,但是指向 可以改变
int const *p; //值不能变,但是指向 可以改变
int * const p; //p的指向不能变 但是 *p的值 可以改变
const int * const p; //p的指向不能变 但是 *p的值 可以改变
volatile :防止编译器优化
volatile关键字声明的变量,编译器对访问该变量的代码就'不再进行优化',从而可以提供对特殊地址的稳定访问。
用 volatile 声明,该关键字的作用是防止编译器直接在CPU寄存器中获取值,在内存中重新读取

4.内存的分段
C语言经过编译之后将内存分为以下五个区域

1.栈:由编译器进行管理,自动分配和释放,存放函数调用过程中的各种参数,局部变量,返回值及函数返回地址。操作方式类似数据结构中的栈。
2.堆:用于程序动态申请分配和释放空间。C语言中的malloc和free,C++中的new和delete均是在堆中进行的。正常情况下,程序员申请的空间在使用结束后应该释放,若程序员没有释放空间,则整个程序结束时系统自动回收。

3.全局(静态)存储区:分为DATA段和BSS段。
        DATA段(全局初始化区)存放初始化的全局变量和静态变量;
        BSS段(全局未初始化区)存放未初始化的全局变量和静态变量。程序运行结束时自动释放。渲校�
BSS段在程序执行之前会被系统自动清零,所以未初始化全局变量和静态变量在程序执行之前已经为0。
4.文字常量区:存放常量字符串。程序结束后由系统释放。
5.程序代码区:存放程序的二进制代码。
5.指针、数组和地址之间的关系是的什么?
数组是保存在一片'连续内存单元'中的,而'数组名'就是这片'连续内存单元'的'首地址',
内存单元的地址就是指针,因此数组名也是一个指针
#数组是由多个数组元素组成,元素按其数组类型的不同,所占连续内存的大小也不同。
一个'数组'的元素的首地址就是其所占连续'内存单元'的'首地址', '指针'变量'既可以指向'一个数组,'也可以指向'一个数组元素。
将'数组名'或'数组的第一个元素'的'地址'赋给指针,指针就指向了一个数组。
如果想使指针变量指向第i个元素,就可以把i元素首地址赋给它。

6.与内存息息相关的重要概念有哪些?
(野指针、栈(stack)、堆(heap)、静态区)
野指针:定义了一个指针变量没有进行初始化,该指针指向了一个不确定的空间,这个指针称为野指针
        造成野指针的几种情况
                a. 定义的指针变量没有被初始化
                b. 指针的操作超过可变量的作用范围(越界)
                c. 指针被释放或者删除后,没有被置为NULL,然后再次被使用
栈(stack):栈是用来保存局部变量(系统自动申请释放),栈上的内容只在函数的范围内存在,函数运行结束这些内容也会被销毁,栈的特点就是效率高,但空间大小有限

堆(heap):堆是由malloc()、calloc()、等函数或者new操作符获得的内存,由free()函数和delete()函数释放内存、堆的特点就是效率高,程序员手动申请释放,但空间大小有�
        #⒁猓旱闭飧龀绦蚪崾诙亚昵氲目占湟部梢员幌低呈头�

静态区:静态区用于保存自动全局变量和static变量,静态区的内容在整个程序中都存在,由编译器在编译的时候分配内存

7.智能指针是什么
8.c++11新的特性
9.tcp四次挥手 以及最后的timewait是干啥的
10.引用指针区别

11.动态库 静态库  dll恶梦1.静态库是在链接阶段,将库和目标二进制文件合并到一起,形成一个整体,编译出可执行文件。会造
成可执行文件较大的现象,但是运行速度也就是调用函数的速度快。在软件更新时需要重新去编译成可执行
文件。静态库是以.a为后缀的。
2.动态库是在链接阶段,在目标二进制文件中创建一个库函数表单,指定链的库函数。库和可执行文件
两者相互独立所以,生成的可执行文件较小,因为需要去外部调用函数,所以速度较慢,但是更新时无需重
新编译,只需要更改库函数的实现就好了。动态库是以.so为后缀的
12.深层复制和浅层复制
13.stl 函数模板类模板14.几种调用约定的区别
  __cdecl __fastcall与 __stdcall,三者都是调用约定(Calling convention),它决定以下内容:
1)函数参数的压栈顺序,
2)由调用者还是被调用者把参数弹出栈,
3)以及产生函数修饰名的方法。   


15.联合体中不能放含有拷贝构造函数的成员
union 不能包含string
union UnST
{
        int i;
        //string str;  //这个不允许
};
联合体中不能放含有拷贝构造函数的成员

16.多线程安全
用户态与内核态

每个进程都拥有所有的虚拟地址空间,当进程运行用户代码的时候是运行在用户地址空间的,这时候 CPU 运行所需要的指令和数据都保存在用户空间,进程可以认为是指令 + 数据 + CPU,因此这个时候我们把这个状态的进程叫做用户进程。当用户执行系统调用而陷入内核代码中执行的时候,当前进程运行的指令和数据都在内核空间,因此我们把这个状态的进程叫内核进程。用户进程和内核进程不是独立的两个进程的意思,而是进程运行的不同状态。值得注意的是,用户进程不能访问内核虚拟地址空间,内核进程可以访问全部的虚拟地址空间,因此用户进程和内核进程进行数据交换只能通过内核进程从用户地址空间取数据,然后放入用户地址空间。


互斥:'同一时间'只能有一个线程执行,执行'完毕后'其他线程再执行   --- 互斥锁
同步:在'互斥的基础上''有顺序'执行 ---  信号量 条件变量
互斥锁的实现原理?
'多个线程'如果要'对'同'一个共享资源进行操作'
'谁抢占到'资源,就对共享资源的操作'进行上锁'
'其他线程需要等待',当第一个线程对共享资源的'操作执行完毕后就解锁',解锁之后
'其他线程'就可以在对这个资源进行操作,
操作之前还是得'上锁'
'操作完毕后'还是得'解锁'
解锁之后其他线程又可以操作,
--以此类推--

临界资源:多个线程'共享的资源'叫做临界资源,它的改变有可能影响到其他线程的使用结果。
临界区:'操作'临界资源的'一段代码'

.简述死锁的情景?
死锁的概念:
多线程以及多进程改善了系统资源的利用率并提高了系统的处理能力。然而,'并发执行'也带来了新的问题——--死锁。所谓死锁是指'多个线程'因'竞争资源'而造成的一种'僵局(互相等待)'',若无外力作用,这些进程都将无法向前推进

产生的原因:
1.对不可剥夺资源的竞争,才可能产生死锁(如磁带机、打印机)
2.进程推进顺序非法,请求和释放资源的顺序不当,也同样会导致死锁

简述信号量的原理?
信号量主要解决同步问题
信号量的本质是PV操作(P是- V是+)
信号量本质是一个计数器,对计数器有两个操作,P操作和V操作,P操作是减操作,V操作是加操作,
当信号量的值为0时,P操作将会阻塞,V操作没有影响
默认线程中的信号量PV操作执行一次只能减1或者加1




17.多态 虚函数
http://firemail.wang:8088/forum. ... 4296&extra=page%3D4

首先我们需要知道几个关键点:

  • 函数只要有virtual,我们就需要把它添加进vTable。
  • 每个类(而不是类实例)都有自己的虚表,因此vTable就变成了vTables。
  • 虚表存放的位置一般存放在模块的常量段中,从始至终都只有一份。


18.C++对象模型

19.
TCP为什么要进行三次握手
第一次握手:'客户端'向'服务器端'发送'连接请求',TCP包头中SYN置1,自己的随机序列号seq为x。

第二次握手:当'服务器端'接收到'客户端'的连接'请求',发现SYN为1,解析获得客户端的随机序列号后。
        向'客户端'发送的TCP包头中SYN置1,应答序列号ACK置1,应答序列号ack为客户端的随机序列号加一(x+1),自己的随机序列号seq为y。
      
第三次握手:'客户端'接收到'服务器端'的'忧肭�'和'应答'后。向'服务器'发送'应答信号',应答标志位ACK置1,应答序列号为服务器的随机序列号加一(y+1)

为什么是三次?
        三次握手的目的是'确保服务器'和'客户端'都具有'收发数据'的能力,
        第一次握手成功说明'客户端'有'发数据'的能力,
        第二次握手成功说明'服务器'有'收发数据'的能力,
        第三次握手成功说明'客户端'有'接收数据'的能力,
所以三次握手的过程缺一不可,但是,如果说超过三次的握手次数,会浪费资源和时间

四次挥手
TCP协议是一种'面向连接'的、'可靠'的、基于'字节流'的传输层通信协议。
TCP是'全双工'模式,
这就意味着,
当 Client 发出FIN报文段时,只是表示 Client 已经'没有数据要发送'了,Client 告诉 Server,它的数据已经全部发送完毕了;但是,这个时候 Client 还是'可以接受'来自 Server 的数据;
当Server '返回ACK报文'段时,表示它已经知道 Client 没有数据发送了,但是 Server 还是'可以发送数据'到 Client 的;
当 Server 也发送了FIN报文段时,这个时候就表示 Server 也'没有数据要发送'了,就会告诉 Client ,我也没有数据要发送了,之后彼此就会愉快的中断这次TCP连接。


20.io模型有哪几种
阻塞I/O: 最常用、最简单、效率最低
非阻塞I/O: 可防止进程阻塞在I/O操作上,需要轮询
I/O 多路复用: 允许同时对多个I/O进行控制(用一个阻塞函数,阻塞所有阻塞函数)
信号驱动I/O: 一种异步通信模型(好像也是学过的唯一的一个异步IO)

21.C++有哪些性质(面向对象特点)
面向对象的三大特征 : 封装 继承 多态 -----// 如果有四:加一个 抽象
22. 引用与指针的区别
1. 引用必须'初始化' ,指针可以'不初始化'
2. '引用不可以改变指向' ,指针可以
3. '不存在指向NULL的引用', 指针可以指向NULL
4. '指针'在使用前需要'检查合法性' ,引用不需要


23. 有哪几种情况只能用intialization list(初始化列表) 而不能用assignment?
必须使用初始化表的场景
1. '成员变量名字'和'构造函数形参名字'冲突时;---也可以用this解决
2.类中包含' const '成员变量时 //因为 const 只能在初始化的时候赋值
3.类中包含' 引用' 成员变量 //引用 只能先指向 再操作
4.类中包含'成员子对象'(类中包含其他类对象时)时
//必须使用初始化表调用子对象的构造函数 完成对成员子对象的初始化  
  //构造函数 才有初始化 表

24.C++是不是类型安全的?
不是。两个不同类型的指针之间可以强制转换(用reinterpret cast)。C#是类型安全的
25.描述内存分配方式以及它们的区别?
1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static 变量。

2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集。

3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc 或new 申请任意多少的内存,程序员自己负责在何时用free 或delete 释放内存。动态内存的生存期由程序员决定,使用非常灵活,但问题也最多。


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|firemail ( 粤ICP备15085507号-1 )

GMT+8, 2024-3-29 19:42 , Processed in 0.057567 second(s), 20 queries .

Powered by Discuz! X3

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表