C面试宝典

更新时间:2024-03-18 00:25:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

1、数据类型

在C/C++中,数据类型分为两种,简单类型和结构类型,简单类型包括整数类型、字符类型、浮点类型、指针类型、枚举类型和void类型。 结构类型包括:数组、字符串、记录和文件。 C/C++中的基础数据类型分为三种:整型、浮点型和void型,其中不能定义void类型的变量,它仅仅是用于说明函数没有返回值和说明指针是无类型。

其中整型是用来表示没有小数位的数,在C/C++中,用来表示整数、字符、布尔值的算术类型合称为整型。在32位机器中,int和long的长度通常是相等的。

2C/C++中的常量

通过关键字const常量也被称为常数,是指在程序运行之前就已经被确定,在程序的运行过程中不会发送改变。常量必须在定义的时候进行初始化。

常量本身没有地址属性(除字符串常量外),而变量有地址属性,所以常量只能做右值,而变量左值、右值都可以。

const char a=”test”正确 char p; p=”test”;

const test=p;错误;常量必须直接赋值。

3、逻辑操作

逻辑操作分为逻辑或、逻辑与和逻辑非3种,其中逻辑或和逻辑非存在“短路求值”的情况。 C++中变量为程序提供了可以操作的有名字的存储区。 变量代表分配了一块存储区 变量代表这个存储区的名称

4 、C/C++中的左值和右值

实际上,左值是一个存储地址,也就是一块内存存储数据所要操作的地址,而右值是一个具体的数据或者数值,也就是该内存存储的数据内容。其中数字字面上是右值,不可以进行赋值。

左值可以出现赋值语句的左边或者右边,也就是说左值可以当右值使用,右值只能出现在赋值的右边,

在C++中变量在定义的时候没有初始化,它的值将是不确定的,不确定的值可能导致程序出现错误。

5 、变量的声明和定义的区别

声明分为定义性声明和引用性声明。其中引用性声明我们叫做声明,定义性声明我们叫做定义,定义和声明最主要的区别在于定义要分配空间和声明不需要分配空间。

C++程序通常由许多文件组成,为了让多个文件访问相同的变量,声明通过关键字extern。表明该变量已经在别的文件中定义,此处只是使用一下。 变量只能定义一次,而声明可以存在多次。

4 、变量有哪几种存储类型

变量的存储类型是从时间上进行划分的,分别是静态存储方式和动态存储方式。 动态存储变量是指程序运行到该变量的时候才为其分配内存空间,当程序离开该变量所在的作用域时自动收回为其分配的存储空间。

5、引用&

C++中引入了引用的概念,引用的定义是在变量前加标识符&,引用是一个对象的别名,是C++中对象的另外一个名字。引用的主要作用作为函数的形式参数。引用必须进行初始化,且初始化对象必须是一个对象,例如: int a=100;

int&refa=a;//&refa引用a

int&refa=b;//错误:引用必须初始化

int &refa=10;//错误,初始化必须为一个对象(变量)。

6 C与C++有什么区别?

C语言是结构化的编程语言,它是面向过程的,而C++是面向对象的。

C语言提供的3种预处理功能分别是:宏定义、文件包含和条件编译。

7 如何分配和释放存储空间

new在C++中是一个关键字,它的使用操作结果是在申请一段指定数据类型大小的的内存。使用方式为指针变量=new 数据类型。new使用后处理的3件事情,如下所示: 1> 计算指定数据类型所需的内存空间 2> 正确的指针内存

3> 分配内存,初始化分配内存 例: int *p; p=new int;

p指向一段由new分配而来的新内存空间,最终p存储的是一个变量的地址。 delete释放指针所指向的内存空间。

8 虚函数和纯虚函数

虚函数的主要作用是建立抽象模型,从而达到方便扩展系统的目的。

纯虚函数是虚函数的一个子集,用于抽象类,基类中不能对虚函数给出有意义的实习,它的实现留给派生类去做这就是纯虚函数,纯虚函数用于抽象类中,不能生成对象。

虚函数必须是基类的非静态成员函数,其访问权限不可以实private。可以是public或者protected。

为了方便多态性,引用了纯虚函数,在编译的时候需要在派生类中必须予以重载以实现多态

性。

9 指针

指针是用来存储内存地址的变量,程序中的所有变量和常量都存储在内存地址中,这个内存地址表示变量和常量在内存中的存储位置,同样地,函数也是有内存地址的。指针用于指向对象,对对象的间接访问。

10 指针与数组

指针和数组有密切的关系,在表达式中使用数组名时,该数组名会自动转换为指向数组第一个元素的指针。

11、const修饰指针

const位于*的左侧,指针所指的内容不可变

const位于*的右侧,指针本身为常值,但指向内容可以变 const int *a=&b;//指针所指的内容不可以改变

int * const a=&b;//指针本身不可以改变,即a不可以改变。可以变为a=&c;

12 this指针

在C++中this指针表示当前运行的对象,在实现对象的方法时,可以使用this指针来获得该对象的自身引用。this指针是一个隐含的指针,指向当前对象,表示当前对象的地址。

13 函数的参数

函数的参数有三种形式:值传递,引用传递,指针传递

15数组指针和指针数组 强调的都是最后一个字,数组指针是指指向一个数组的指针,指针数组是指数组元素都是指针的元素的数组。

14、指针和引用的区别

指针和引用都是地址的概念,指针是指向一块内存,它的内容是内存中地址,而引用是模块某块内存的别名,指针是作为一个真实的实体而存在。 区别:

1> 指针是一个实体(真实而存在的东西),引用只是一个别名。

2> 在内存分配上,程序要为指针分配内存,而引用是一个别名,不用为其分配内存空间 3> 引用只能在定义时被初始化一次,之后不可变,指针可以变化。 4> 引用不能为空,而指针可以为空。 5> 引用无const,而指针有const关键字

6> ” sizedof引用”得到的是所指向的变量的大小。“sizeof指针”得到的是指针本身的大小。

面向对象的3个基本要素:封装、继承、多态

15 抽象类及它的用途

抽象类可以提供多个派生类共享基类的公共定义的定义,它可以提供抽象方法,也可以提供非抽象的方法,抽象类不能够实例化,必须通过继承实现其抽象的方法,抽象类不能使用new关键字,它也不能被封装,如果派生类没有实现所有的抽象方法,则该派生类也必须声明为抽象类。派生类用覆盖(重写)的方法来实现抽象的方法。 抽象类一定含有纯虚函数,因此不能定义抽象类的对象

包含纯虚函数的类成称为抽象类,抽象类把含有共同属性和方法的对象抽象成功一个类。

16 如何访问静态成员

静态成员的关键字为static,能够在类的范围内所有对象共享的,而不是被某个对象所独有的成员变量,因此静态函数中不含有this指针,this指针始终指出当前对象, 在类中使用静态成员,可以实现多个对象之间数据的共享,派生类和基类可以共享静态成员,类的静态成员可以独立访问,也就是说不需要创建类的实例(对象)可以访问静态成员。其中类的静态方法只能调用静态成员,

类的静态成员在类加载时就已经生成,生命周期长于对象。

17 多态性

在C++中多态性是通过虚函数实现的,多态性是指允许将子类类型的指针复制给父类类型的指针,多态是行为上的一种封装,“一种接口,多种实现”。多态的主要作用是以下两点: 1>精简代码的量

2>派生类的功能可以被基类的方法或引用变量所调用,这称为向后兼容性,很大程度上提高可扩充性和可维护性。

派生类总是可以转换为基类的引用类型。可以实现向后兼容性。

18 虚成员

虚成员也称为虚函数,虚函数主要实现多态的机制,虚函数的核心理念就是通过基类可以访问派生类定义的函数,虚函数必须是基类中非静态的成员函数。它的访问权限为public或者protected。可以通过指向基类的指针或者基类的引用对象来调用派生类的实现了的虚函数。

19 构造函数和析构函数

构造函数和析构函数都是自动调用的函数。析构函数与构造函数均无返回值,构造函数用于在创建对象时初始化对象,即为成员变量赋初值, 构造函数必须与类名相同,无返回值(没有返回类型),也不能用void修饰。可以进行重载。 析构函数与类名相同,且前面加了~,析构函数无返回值,不带参数,不可以重载。

拷贝构造函数

拷贝构造函数是一种特殊的构造函数,函数的名称必须与类名相同,且有且只有一个不可变参数,参数是本类型的一个引用变量,该参数是const类型,不可变的,例如:类X的拷贝构造函数的形式为X(X& x)。

拷贝构造函数又分为浅复制和深复制,它们的主要区别在于引用对象有没有为分配空间。 深复制(深拷贝)和浅复制(浅拷贝)区别:最主要的区别在于对象资源的复制,而浅复制只是一个新的引用指向了资源。

杂记:

形参是函数定义时在形参表中定义的,并且由调用函数调用时传递函数的实参所初始化的。 内敛函数:在类声明的内部声明或定义的成员函数叫做内敛函数,在内敛函数中不允许使用循环语句和开关语句。

20 容器

容器是容纳特定类型对象的集合,可以认为是数组的扩展,即对象的数组,迭代器可以进行容器的遍历。

杂记:数组名作为函数的参数时,在函数体内就变成一个指针。 void Func(char str[100]){ sizeof(str); }

sizeof(str)=4;

Func(char str[100])函数中数组名作为函数形参,在函数体内函数名仅仅是一个指针,可以做自增、自减操作。

21 算法

直接插入和选择排序、希尔排序、

选择排序:首先在未排序序列中找到最小元素,存放到排序序列的起始位置,然后,再从未排序序列中继续寻找最小元素,然后放到排序序列末尾。以此递归。

直接插入排序:逐一取出元素,在已排序的元素序列中从后向前扫描,放到合适的位置,注意(起初,原始排序序列为空)。

希尔排序:希尔排序是较为复杂的插入排序。

软件工程

22 软件开发的模型

软件开发的模型有四个,瀑布模型,原型模型、螺旋模型、增量模型 瀑布模型, 在瀑布模型中,软件的各个活动严格按照线性方式进行,当前活动接受上一个活动的工作结果,实施完成所需的工作内容。瀑布模型的特点:

1> 具有顺序性和依赖性必须等待前一阶段工作的完成,才能开始后一工作阶段。 2>

瀑布模型的缺点:

1> 依赖早期进行的唯一的一次需求调查,不能适应需求的变化

2> 风险往往推迟到后期的开发阶段才暴露出来,失去及早更正的机会

瀑布模型一般适用于需求清晰明了且时间要求宽松的软件开发项目,规模小、需求简单。功能单一的项目,

原型模型:原型模型是可以快速建立起来的在计算机运行的程序。它的功能往往是最终产品功能的一个子集。 原型模型的特点:

1> 用户需求不完全或不确定

2> 针对总体的轮廓先建立一个用户需求原型,然后进行反馈和评价。 3> 对原型进行扩充、改进和求精 4> 完成最终系统 原型模型的缺点:

原型模型的目的是用来进行演示的,实际用来操作时不行的,不可以进行详细的输入输出。

螺旋模型:瀑布模型与原型模型结合起来,并且加入了两种模型均忽略的风险分析。螺旋模型的特点是风险进行驱动的,关注风险,进行风险分析后进行决策是否进行项目。用于大规模软件项目,需求不明朗,风险比较高的项目。

增量模型:增量模型融合了瀑布模型的基本成分和原型模型的迭代特征,采用随着日期的进展而交错的线性序列。其特点是第一阶段增量往往是核心产品,每一个阶段增量均可以发布一个新的产品,早期的版本是最终产品的可拆卸版本,用于需求逐渐清晰的产品。

23 四种开发模型的选择

瀑布模型:需求明确且时间要求宽松的软件开发项目或者规模小,功能单一的产品。

原型模型:适用于客户能提出的一般性的目标,但不能标出详细的输入、处理及输出需求、 螺旋模型:大规模软件项目,需求不确定,风险比较高的项目 增量模型:需求逐渐清晰的项目。

24 软件测试

软件测试就是为了发现软件中的错误,软件测试的过程就是软件运行的过程, 测试用例:在软件运行的时候,针对不同的运行情况进行不同的数据输入和操作。 白盒测试:

黑盒测试:为了证实软件的各个产品功能,黑盒测试在软件的接口上进行测试。 白盒测试:对程序的内部逻辑结构和内部逻辑进行测试。

25白盒测试的设计原则

1>保证模块的每一个独立路径至少执行一次 2>保证所有判断的每一个分支被执行一次

3>保证循环都在边界条件和一般条件下各执行一次

5> 验证所有内部数据结构的有效性。

26 设计模式的分类:

27关系数据库设计范式

数据库:按照一定数据结构来存储和管理数据的软件系统。 关系数据库设计范式是指设计数据库时,遵守一定的设计原则。

第一范式:确保每一列的原子性(每一列都是不可再分割的最小数据单元)。 第二范式:在第一范式的基础上,确保每一列都和主键相关。

第三范式:在第二范式的基础上,确保每一列都和主键有直接的关系,在第二范式的基础上消除了传递依赖。 28 事务

事务是指单个逻辑单元的一系列操作,这些操作要么全做,要么全不做。所有的操作是一个整体,不可分割。

事务的四大特性(ACID):

1>A 原子性指事物是一个逻辑工作单位,要么全做,要么全不做

2>C一致性指事物执行的结果必须使数据库从一个一致性状态转换到另外一个一致性的状态。

3>I 隔离性事务之间不能相互干扰,并发执行的事务之间相互不干扰 4>D 持续性指事物一旦提交,其对数据库的改变是永久不变的

29 游标的含义以及作用 游标相当于一段缓存区域,可以从多条记录的结果集中每次提取一条纪录的机制(感觉有点像迭代器),

游标的主要作用就是保存查询的结果集,以便以后使用,游标的结果集是由select语句产生,如果处理过程需要重复使用一个记录集,那么创建一次游标而重复使用若干次,比重复查询数据库快很多。

21操作系统根据任务的处理方式可以分为简单的批处理,多道程序批处理系统,多道程序分时系统,网络操作系统

22进程和线程的区别

进程是指一个程序中正在运行的应用程序,一个进程至少包括一个线程,操作系统中最小的调度单位是线程,资源最小的单位是进程。进程是资源分配的最小单位。

进程为应用程序的运行实例,是应用程序的一次动态执行,一个进程可以包括若干个线程,使用线程可以实现应用程序同时做几件事情并且不相互干扰,

线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有资源,线程和同属于一个进程的线程共享进程的所有资源,同一个进程中的多个线程之间可以并发执行。

1>一个程序至少一个进程,一个进程至少一个线程

2>进程在执行的过程中拥有独立的内存单元,而多个线程共享进程所拥有内存 3> 进程可以独立运行,但线程不能给独立运行,必须存在进程中。

23 如何实现多线程同步

多线程同步的基本思想就是避免多个线程对同一资源的访问,可以利用临界区,信号量、互斥量等实现。

24OSI的7层模型

1>物理层:实实在在存在的链路,进行物理特征,电气特征、,进行比特的传输,同轴电缆工作在这一层。主要的工作协议为IEEEE, 2>数据链路层:主要作用物理寻址,将上层(网络层)的包分割成帧、流量控制、数据检错、重发等,工作协议有 。

3>网络层:网络层将地址转换成物理地址,并且将数据从传送方发送到接受方,主要进行负责管理网络地址,地位设备,决定路由,路由器工作在这一层,这层数据为包,,主要作用进行路由选择,拥塞控制,网络互联,主要协议有IP,RIP 4>传输层:负责组合和分割数据,组合成段,负责端到端的传输,还有差错控制和流量控制,三次握手、面向连接、和面向非连接的服务、流量控制都发生在这一层,主要的协议有TCP、UDP、SCTP。

5>会话层:负责在两个网络节点之间建立、维护、控制会话,区分不同的会话

6>表示层:该层是界面和二进制编码直接相互转化的地方,该层负责数据的压缩、解压、加密、解密、该层根据不同的应用目的将数据处理为不同的格式。 6> 应用层:为操作系统或网络应用程序提供访问网络服务的接口。常见的协议为http、ftp、

snmp 传输层是第一个端到端通信,传输层提供应用进程间的逻辑通信。而网络层提供点与点之间的通信(它只提供从一台机器到另一台机器之间的通信)。

25 交换机与路由器的区别 主要区别有三个:

1>工作的层次上,交换机工作数据链路层,路由器工作在网络层,

2>转发数据所依据的对象不同,交换机根据MAC地址(物理地址)进行转发到数据的目的地址,其中MAC地址(物理地址)是硬件自带的,固定的,一般是不可变的, 而路由器根据IP地址进行转发到数据的目的地址,IP地址是在软件中实现的。可以进行

改变。

3>广播域上,由交换机连接的网段仍属于同一个广播域,而路由器可以分割广播域 。

引申:集线器和交换机的区别

1>工作层数不同,集线器工作在物理层,对接受到的数据进行信号放大,交换机工作在数据链路层,还可以对数据进行转发, 2>工作方式不同,集线器是一种广播方式,交换机能够隔离冲突域和有效的抑制广播风暴的产生。

3>集线器是一种半双工的模式,交换机可以是全双工的模式 4>

26 路由器的工作原理

路由器根据路由表选择最佳的工作路径到目的地址,其中路由表分为静态路由和动态路由 静态路由是由网络管理员手工配置的路由信息,动态路由是路由器自己能够动态建立自己的动态路由表。

27 TCP和UDP的区别有哪些?

TCP和UDP都是工作在传输层进行数据段的传输,其中TCP就像打电话一样,必须和对方建立联系,而UDP就想发短信一样,只把信息发出去(尽最大可能的支付)。 区别:

1>TCP提供连接的传输控制协议,而UDP提供无连接的数据报服务。

2>TCP具有高可靠性,确保传输数据的正确性,不会出现丢失或者乱序,UDP可能会出现一些问题。

3>TCP对系统资源要求较高,UDP对系统资源要求较少,

4>UDP具有较高的实时性,工作效率高于TCP,因此UDP用于QQ聊天中。 4> UDP的段相对于TCP而言较为简单,因此网络开销也少。 DNS通常都是基于UDP协议。

28 三次握手四次断开

三次握手是指在TCP/IP协议中,通过三次握手建立连接:

第一次:客户端向服务器发送SYN包,并进入SYN—SEND状态

第二次:服务器向客户端发送确认的包ACK包和SYN包,并进入SYN_REVD状态

第三次:客户端收到服务器发送的ACK+SYN包,向服务器发送确认包ACK,服务器和客户端同时进入ESTABLISHED,其中ACK与序列号有关。

四次断开:

(1)客户端发送数据完毕之后,发送一个FIN,提出断开请求

(2)服务器收到FIN后,对其做出响应,首先发送一个ACK包,确认这一方向的连接将关门,进入CLOSED_WAIT状态。此时客户端进入FIN_WAIT1状态,随后进入FIN_WAIT2, (3)服务器做好准备关闭的状态后,向客户端发送FIN,请求关闭连接。

(4)客户机对服务器发送的请求进行确认,并发送ACk包。双方均进入CLOSED状态。

ACK确认。

SYN在连接建立时用来同步序号,当SYN=1而ACK=0时,表示这是一个连接请求报告,对方若同意建立连接,则应在响应报文中使用SYN=1和ACK=1。SYN置1就表示这是一个连接请求或连接接受报文。

FIN(finins)即完,终结的意思,用来释放一个连接。当FIN=1,表明此报文段的发送方的数据已经发送完毕。

这为什么采用三次握手而不是两次确认?

这主要防止以失效的连接请求报文段突然又传到B,如果不采用三次的话,B发出确认,就是新的连接就建立了。

失效的连接发出请求时,B以为新的连接建立,并一直等待A发来的数据,就会造成B的资源浪费,

关闭的时候,TCP客户端发送一个FIN,这时客户端的连接已经关闭,客户端不能再发送信息,但可以接受信息。

服务器收到FIN后,向客户端发回一个ACK,然后服务器关闭客户端的连接,发送一个FIN给客户端(服务器关闭到客户端的连接),

客户端收到确认信息后,进入等待状态,等待服务器关闭连接的请求FIN=1,客户端收到后回复一个确认信息进入TIME_WAIT,等待2ms后关闭。

TCP为何采用四次会受释放连接?

关闭连接时,当收到对方的FIN报文通知时,仅表示对方没有数据发送给你了,请求关闭连接,而仍然可以接受数据,但未必你所有的数据都全部发送给了对方,所以你未必会马上关闭Socket,等你的数据全部给对方后,再发送一个FIN报文给对方,针对每一个FIN报文,都要有一个ack报文。

面向连接的客户端Socket程序的主要步骤? 1) 创建套接字(Socket());

2) 向服务器发送连接请求(connect()); 3) 和服务器进行通信; 4) 关闭套接字(close());

面向连接的服务器端Socket程序的主要步骤? 1) 创建套接字(Socket()); 2) 进行绑定(bind( )); 3) 进行监听(listen( )); 4) 进行accept();

5) 和客户端进行连接 6) 关闭套接字(close())

29 什么是ARP/RARP

ARP是地址解析协议。根据IP地址获取物理地址(MAC地址)。

ARP的工作原理:首先每一个主机都有ARP地址列表,用户存储IP地址和MAC地址直接的对应关系,

然后当源主机将数据发送到目的主机时,会先检查自己的ARP地址列表中是否存在该IP地址和MAC地址的对应关系,若存在,直接将数据发送到该MAC地址,

否则,向本地网段发起一个ARP请求的广播包。用于查询目标主机所对应的MAC地址,此ARP数据请求包中含有源主机的IP地址,物理地址,目的主机的IP地址等,本网络中所有收到ARP请求之后,会检查数据包中的IP地址和自己的IP地址是否相同,如果不相同,则丢弃,

若是相同,该主机将把源主机的IP地址和MAC地址添加到自己的ARP列表中,接着给源主机发送一个响应包,将得到的目的地址的IP地址和MAC地址放到源主机的ARP地址列表中,并且利用此信息进行传输。

RARP:通过MAC地址获取IP地址,

RARP的工作原理:首先未知的IP主机向一台服务器发送消息,并等待服务器的响应,开始并不知道服务器的IP地址,可以通过广播的方式,一旦通过广播地址的方式,就必须唯一地标识自己的硬件地址,这个标识很容易被程序识别,源主机收到响应的消息后,就可以利用得到的IP地址进行通信了。

30 Ping命令是什么?

Ping是用于测试网络连接量的程序。Ping使用的是ICMP(网络控制管理协议),ICMP协议

用于在IP主机、路由器之间控制消息,它是用来检查网络是否通畅或者网络连接速度的命令。

Ping加的是对方的IP地址(或者域名)利用DNS域名服务器,

31 基本的HTTP流程有哪些?

1>打开连接,HTTP是一种无状态连接,所以每一个请求都需要建立一个新的连接。 2>初始化请求方法例如GET/post

3>设置HTTP请求头。包括要传输的数据类型和数据长度 4>发送请求 5>读取请求

7> 初始化响应方法 8> 设置HTTP响应头 9> 发送响应 10> 关闭连接

网络中客户端与服务器的连接: 先从服务器说起,服务器先调用Socket函数,然后进行绑定(bind),对端口进行监听(listen),调用accept,等待客户端的连接。

客户端调用Socket,然后连接服务器connect,这是服务器和客户端就建立了联系,客户端发送数据请求,服务器端接受并处理请求,然后把响应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。

主机号全为0表示本网络本身,主机号全为1表示本网络的广播地址。

子网掩码:左边是网络位,右边是主机位,1的数目等于网络位的长度,0的数目表示主机的长度。很容易通过0的个数确定子网的主机数,(2的主机位数次方-2,因为全主机号为1表示该网络的广播地址,全0表示该段的网络号)。

http中的状态码

1xx:消息。代表请求消息已被正确接收,需要继续处理 2XX:成功,

代表请求已成功被服务器接受、理解、 3XX:重定向

4XX:客户端错误,当前请求无法被服务器理解 5XX:服务器错误。

输入HRL按下回车后发生了什么?

1) 浏览器向DNS服务器查询URL对应的IP地址 2) DNS服务器返回IP

3) 浏览器打开TCP连接,并向web服务器发送HTTP请求 4) 服务器处理请求,并返回HTML响应 5) 浏览器接受响应的HTML并进行渲染, 6) 浏览器关闭TCP连接。

telnet可以检测web服务器是否可以正常工作。

本文来源:https://www.bwwdw.com/article/bsf8.html

Top