20240820
一、
1.C语言中指针数组和数组指针的区别
答:指针数组本质上是一个数组,是一个指针变量的集合,即数组内的元素都是指针变量,类似于二维数组中存储的多个一维数组;数组指针本质是一个指针,是整个数组的起始地址,它的偏移量是整个数组的长度
参考答案:
1.定义方式:指针数组是一个数组,其中的每个元素都是一个指针;数组指针是一个指针,它指向一个数组。
2.存储方式:指针数组中的每个元素是指针,它们可以指向不同的内存地址;而数组指针本身只指向一个数组,不能用来指向其他数组。
3.访问方式:指针数组可以通过下标来访问每个元素,然后通过解引用指针来访问指向的值;数组指针可以通过解引用指针直接访问数组中的元素。
4.内存分配:指针数组中的每个指针需要单独进行内存分配,可以指向不同的内存地址;数组指针本身只需要分配一个指针的大小,并且只指向一个固定大小的数组。
5.用途:指针数组常用来表示一个字符串数组或多个不同类型的指针集合;数组指针常用来表示多维数组,可以用于传递二维数组到函数中。
2.结构体字节对齐
答:低字节向高字节对齐,32位系统中:min(最大字节数 ,4),64位系统中:min(最大字节数,8);
参考答案:
1.结构体中的每个成员,在分配内存时,要以数据类型对齐一次
2.所有成员分配内存结束后,整体需要对齐一次:
32位系统以 min(最大字节的成员,4) 对齐
64位系统以 min(最大字节的成员,8)对齐
3.TCP和UDP的区别
答:是两种常用的网络传输协议,都适用于基于socket的网络通信方式,
连接方式:TCP是面向有连接的,在进行通信之前,需要与服务器进行三次握手才能建立连接,是点对点的通信;UDP是面向无连接的,可以一对一,一对多,多对多的进行通信;
可靠性:TCP通过对数据包的确认和重传,保证数据的可靠;UDP尽最大可能的进行数据传输,不保证数据完整可靠;
速度:TCP需要确认数据可靠和完整,数据相对较慢;UDP只做数据传输,不进行数据检查,速度较快;
TCP会产生沾包现象,UDP不会;
参考答案:
共同点:同属于传输层的协议,都用于网络传输
TCP ----> 稳定
1> 提供面向连接的,可靠的数据传输服务
2> 传输过程中,数据无误、数据无丢失、数据无失序、数据无重复
1、TCP会给每个数据包编上编号,该编号称之为序列号
2、每个序列号都需要应答包应答,如果没有应答,则会将上面的包重复发送直到正确为止
3> 数据传输效率低,耗费资源多
4> 数据收发是不同步的
1、为了提高效率,TCP会将多个较小,并且发送间隔短的数据包,沾成一个包发送,该现象称为沾包现象
2、该沾包算法称之为Nagle算法
5> TCP的使用场景:对传输质量比较高的以及传输大量数据的通信,在需要可靠通信的传输场合,一般使用TCP协议
例如:账户登录,大型文件下载的时候
UDP ----> 快速
1> 面向无连接的,不保证数据可靠的,尽最大努力传输的协议
2> 数据传输过程中,可能出现数据丢失、重复、失序现象
3> 数据传输效率高,实时性高
4> 限制每次传输的数据大小,多出部分直接忽略删除
5> 收发是同步的,不会沾包
6> 适用场景:发送小尺寸的,在接收到数据给出应答比较困难的情况下
例如:广播、通讯软件的音视频
4.同步通信和异步通信的区别
答:同步通信指在通信过程中在接收消息的同时也能发送消息,但当同时收到多个消息时,只能接收到第一条;异步通信需要对接收到的消息进行确认,而后发送,确保消息不丢失,但效率较慢;
参考答案:
- 执行方式:
-
同步通信是指发送方发送消息后会一直等待接收方的响应,直到接收到响应或超时,然后才能继续执行后续操作。
-
异步通信是指发送方发送消息后不需要等待接收方的响应,可以立即继续执行后续操作,而接收方在接收到消息后会触发相应的处理流程。
- 阻塞与非阻塞:
-
同步通信是阻塞的,发送方在等待接收方响应期间无法进行其他操作。
-
异步通信是非阻塞的,发送方在发送消息后可以继续执行其他操作,不需要等待接收方的响应。
- 可靠性:
-
同步通信通常具有较高的可靠性,因为发送方会一直等待接收方的响应,确保数据的准确性和完整性。
-
异步通信的可靠性相对较低,因为发送方不等待接收方的响应,无法保证数据的准确性和完整性。
- 资源利用:
-
同步通信的资源利用较高,因为发送方在等待响应期间无法释放已占用的资源。
-
异步通信的资源利用较高,因为发送方在发送消息后可以继续执行其他操作,释放已占用的资源。
适用场景:
-
同步通信适用于需要实时响应或确保数据的可靠性的场景,如请求-响应模式的交互。
-
异步通信适用于不需要及时响应或对数据准确性要求相对较低的场景,如发布-订阅模式的消息传递。
5.谈谈你对多线程的理解
答:是轻量版的进程,相较于进程,占用资源极少,一个进程可以包含多个线程,多个线程可以共享一个进程的资源,任务器调度的最小单位,linux中不直接支持线程相关的支持库,需要引入第三方库,线程支持库
参考答案:
多线程是指在一个程序中同时执行多个线程的并发编程模式。线程是操作系统能执行的最小单位,每个线程都有自己的执行路径和执行栈,可以独立执行任务。多线程的主要目的是提高程序的并发性和响应速度,充分利用系统的资源。
多线程的特点和优势包括:
-
并发性:多个线程可以同时执行不同的任务,提高了程序的并发性和并行度。
-
充分利用CPU资源:可以充分利用多核CPU的优势,实现并行计算,提高程序的执行效率。
-
提高响应速度:通过多线程可以将耗时任务和需要实时响应的任务分开执行,提高了程序的响应速度。
-
资源共享:多线程可以共享同一进程的内存资源,提高了资源的利用率。
然而,多线程也存在一些挑战和问题:
-
并发竞态:多个线程同时操作共享资源时可能引发竞态问题,导致数据不一致和程序错误。
-
同步和互斥:为了保证共享资源的正确性,线程之间需要进行同步和互斥操作,增加了编程的复杂性。
-
上下文切换开销:线程的切换会引起额外的开销,包括保存和恢复寄存器状态、切换任务等。
-
死锁和饥饿:不正确的线程同步操作可能导致死锁和饥饿问题,造成程序无法继续执行。
因此,在使用多线程时需要注意线程之间的同步和互斥,合理设计线程的数量和工作负载,避免出现竞态和死锁等问题,以充分利用多线程的优势并保证程序的正确性和稳定性。
二、
1.大小端验证
答:因为CPU架构的不同而在主机上形成的不同存储方式,大端存储:数据高位存储在地址低位,数据低位存储在地址高位,小端存储:数据高位存储在地址高位,数据低位存储在地址低位,验证方式:1.共用体,2.将高字节数据存储到低字节地址中,判断数据高位(低位)的存储位置;
参考答案:
大小端(Endianness)是用来描述计算机中多字节数据(例如整数)在内存中的存储方式的概念。
大端序(Big Endian)是指高位字节存储在低地址,低位字节存储在高地址。类比于数字,就是我们在看数字时先看到高位数字。
小端序(Little Endian)是指低位字节存储在低地址,高位字节存储在高地址。类比于数字,就是我们在看数字时先看到低位数字。
考虑一个16位整数 0x1234,在大端序和小端序的存储方式下,其在内存中的存储如下:
大端序:高字节在低地址,低字节在高地址
```
低地址 高地址
+----+----+----+----+
| 12 | 34 | | |
+----+----+----+----+
```
小端序:低字节在低地址,高字节在高地址
```
低地址 高地址
+----+----+----+----+
| 34 | 12 | | |
+----+----+----+----+
```
在计算机系统中,不同的体系结构采用不同的大小端序,如x86体系结构通常采用小端序,而网络协议通常采用大端序。在进行数据的传输和交换时,需要考虑不同系统的大小端问题。
2.互斥锁相关问题
答:在多线程中,引入互斥锁是为了解决临界资源被抢占和更改过程造成的数据错误问题,本质上也是一个特殊的临界资源,当它被一个线程抢占时,其他线程将不可使用,直到该互斥锁被释放
参考答案:
互斥锁本质上也是一个特殊的临界资源,该临界资源在同一时刻只能被一个线程所拥有,当一个线程试图去锁定被另一个线程锁定的互斥锁时,该线程会阻塞等待,直到拥有互斥锁的线程解锁了该互斥锁互斥锁的基本操作是上锁(lock)和解锁(unlock)。当一个线程或进程需要访问共享资源时,首先尝试上锁,如果成功则可以访问资源,访问完成后再解锁。其他线程或进程在尝试上锁时,如果锁已经被某个线程或进程持有,则会被阻塞等待锁的释放。
互斥锁可以有效地保护共享资源的一致性,避免多线程和多进程并发访问共享资源时产生的竞态条件和数据不一致的问题。但需要注意的是,过度使用互斥锁也容易导致性能问题,因为线程或进程在等待互斥锁时会造成一定的开销。因此,在设计并发系统时需要权衡使用互斥锁的粒度和频率,尽量减少互斥锁的竞争和等待时间。
3.共享内存特点
答:是 system V 提供的一种用于多进程通信的通信方式,是真实内存地址在程序中的映射,进程间可以通过对共享内存的读写进行数据通行,当进程结束,共享内存中的数据也不会被删除;
参考答案:
1、共享内存表示的是多个进程共享一个外部的物理内存,效率比较高
2、共享内存具有时效性,存放到共享内存区域中的数据,如果不及时读取,下一次写入后,前面的数据会被覆盖
3、共享内存的操作不是一次性的,写入到共享内存中的数据,即使读取出去后,依然存在于共享内存,直到下一次被覆盖
4.讲一下C中的指针
答:是变量在内存空间的地址,指向存储在内存空间中的数据,通过对指针的操作,可以快速找到该内存地址下存储的数据
参考答案:
在C语言中,指针是一种用于存储内存地址的变量类型。指针变量存储的是某个对象(变量、函数等)在内存中的地址,通过指针可以访问或操作该对象。
指针的声明和使用主要涉及以下几个方面:
-
指针的声明:指针变量的声明需要指定指针变量的类型。例如,可以使用`int*`声明一个指向整数的指针变量,使用`char*`声明一个指向字符的指针变量。指针变量名前面添加一个星号(*)表示该变量是一个指针。
-
指针的赋值:指针变量可以被赋予一个内存地址。例如,`int* ptr = #`将指针`ptr`赋值为变量`num`的地址,即`ptr`指向了`num`。
-
通过指针访问内存:使用解引用操作符(*)可以获取指针指向的内存中存储的值。例如,`int value = *ptr;`将获取指针`ptr`指向的地址中存储的整数值,并赋给变量`value`。
-
指针的运算:指针变量可以进行递增和递减运算,这将使指针指向下一个或上一个相同类型的内存地址。例如,`ptr++;`将使指针变量`ptr`指向下一个整数地址。
-
空指针:在声明指针变量时,可以将其初始化为一个特殊的值`NULL`,表示指针不指向任何有效的内存地址。空指针在未被初始化或已经释放的指针上执行操作时很有用。
-
动态内存分配:使用`malloc()`函数在堆上动态分配内存,并返回分配内存的地址。这样就可以获得一个指向动态分配内存的指针。使用完动态分配的内存后,需要使用`free()`函数释放内存,以避免内存泄漏。
指针在C语言中广泛应用于各种场景,包括传递参数、数组和字符串处理、动态内存管理等。指针的正确使用需要注意指针的合法性、避免野指针和空指针的访问,以及正确释放动态分配的内存等。
5.有接触过gcc吗,gcc的四步是什么
答:1.预处理:展开头文件,进行宏替换等,2.编译,3.汇编,4.链接
参考答案:
-
预处理(Preprocessing):在编译过程中,首先进行预处理操作。预处理器会根据代码中的预处理指令(例如#include、#define等)对源代码文件进行处理,生成一个被称为"预处理过的源代码"的临时文件。
-
编译(Compiling):在预处理完成后,编译器将对预处理过的源代码进行编译。编译过程会将源代码翻译成为汇编代码,生成一个汇编语言代码文件。
-
汇编(Assembling):接下来,汇编器将汇编代码转化为机器码,生成一个目标文件。
-
链接(Linking):最后,链接器将目标文件与其他的目标文件或库文件进行链接,生成可执行的程序。链接器会解决符号引用(Symbol resolution)和地址重定位(Address relocation)的问题,将各个模块之间的引用关系确定下来,并生成最终的可执行文件。
三、
1.对socket的理解
答:是网络端口间进行通信的基本方式,通过socket()函数可以得到一个套接字文件的文件描述符,
参考答案:
Socket(套接字)是一种用于网络通信的编程接口,它提供了一种可靠和通用的方式来进行网络数据传输。Socket允许应用程序通过网络发送和接收数据,使得不同设备上的应用程序能够相互通信。
Socket使用客户端-服务器模型,其中客户端是请求数据的应用程序,而服务器是提供数据的应用程序。客户端和服务器之间通过网络连接进行通信。通常,客户端发起一个连接请求,服务器接受连接请求,并在双方建立连接后开始传输数据。
Socket通信的实现需要两个主要组件:IP地址和端口号。IP地址用于标识网络中的设备,而端口号用于在设备上引用特定的应用程序。在通信过程中,客户端和服务器应用程序都会绑定到一个特定的IP地址和端口号,以便彼此进行定位和连接。
Socket通信可以使用不同的协议,最常见的是TCP(传输控制协议)和UDP(用户数据报协议)。TCP提供可靠的、面向连接的通信,适用于需要确保数据传输可靠性和顺序的应用程序。UDP则是一种无连接的通信方式,适用于需要快速、实时传输的应用程序。
在编程中,使用Socket API可以实现Socket通信。不同编程语言提供了各自的Socket库或模块,用于创建、绑定、连接、发送和接收Socket数据。开发人员可以使用这些库来实现网络应用程序,例如网络游戏、文件传输、实时数据传输等。
总结起来,Socket是一种网络通信的接口,它通过IP地址和端口号来实现不同设备上应用程序之间的数据传输。使用Socket API,开发人员可以创建网络应用程序,并使用TCP或UDP协议进行可靠和高效的数据传输。
2.HTTP协议和TCP协议和UDP协议之间的关系
答:HTTP协议TCP协议来建立浏览器与服务器之间的通信
参考答案:
HTTP协议、TCP协议和UDP协议是网络通信中的三个不同层次的协议,它们之间存在着一定的关系。
- TCP协议与UDP协议:
TCP(传输控制协议)和UDP(用户数据报协议)是两种不同的传输层协议。它们都属于互联网协议套件,用于在网络上传输数据。它们之间的主要区别在于传输方式和特性:
-
TCP是一种面向连接的协议,提供可靠的数据传输和流控制。它使用三次握手建立连接,并在传输过程中进行错误检测和流量控制。TCP适用于需要确保数据完整性和顺序性的应用,如网页浏览、文件传输等。
-
UDP是一种无连接的协议,提供快速和简单的数据传输。它不进行连接建立,也不提供可靠性和流量控制,只负责将数据从源传输到目的地。UDP适用于需要快速传输和实时性要求较高的应用,如视频和音频流传输。
- HTTP协议与TCP协议:
HTTP(超文本传输协议)是一种应用层协议,用于在Web上传输超文本和其他资源。HTTP协议依赖于底层的传输协议,通常使用TCP作为传输层协议。具体来说,HTTP使用TCP的连接功能来建立与服务器的连接,并通过TCP的可靠性和流量控制机制来确保数据的可靠传输。
所以,HTTP协议在传输层上依赖于TCP协议,而TCP协议则可以在IP协议上使用。另外,UDP协议也可以被HTTP协议所使用,但是这种情况相对较少见,因为UDP不提供可靠性保证,适用性有限。
3.IP地址和子网掩码如何决定网络所在的网段
答:IP地址 & 子网掩码
4.计算机网络中的OSI七层模型和TCP/IP四层体系结构
答:OSI七层模型:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层
TCP/IP四层体系结构:数据链路层、网络层、传输层、应用层
5.数据结构中栈和队列的区别
答:都是一种操作受限的存储结构,对于栈而言,它只有一个端口,存储数据(压栈)和读取数据(出栈)都只能在一个端口操作,且先进栈的数据后出栈,后进栈的数据先出栈,对于队列而言,它的操作需要在两个不同的端口进行,一个对应出口,一个对应入口,先入队的数据先出队,后入队的数据后出队
参考答案:
栈和队列是两种常见的数据结构,它们在数据的组织和操作方式上存在一些区别。主要区别如下:
-
存储方式:栈(Stack)使用的是"后进先出"(Last-In-First-Out,LIFO)的存储方式,而队列(Queue)使用的是"先进先出"(First-In-First-Out,FIFO)的存储方式。
-
插入和删除操作:栈只能在栈顶插入和删除元素,即只能对栈顶进行进栈(Push)和出栈(Pop)操作。而队列可以在队尾插入元素,称为入队(Enqueue),在队头删除元素,称为出队(Dequeue)。
-
操作限制:栈的限制性操作是对栈顶元素的访问和控制,因为只有栈顶的元素是可见的。队列没有类似的限制,可以访问和控制队列的任意位置。
四、
1.顺序表和链表的区别
答:顺序表本质上就是一个数组,表中的元素在物理地址上是连续的,而链表是直接用指针来进行数据存储,各个元素之间的地址不一定连续,顺序表元素可以直接通过下标访问,访问效率高,链表只能需要逐个遍历查找数据,访问效率低,顺表的插入和删除需要移动大量的数据,而链表则不需要,效率更高
参考答案:
-
存储方式:顺序表使用连续的内存空间存储元素,而链表使用离散的内存空间通过指针链接每个节点。
-
插入和删除操作:顺序表插入和删除元素需要进行元素的移动操作,时间复杂度为O(n),其中n为元素个数。而链表插入和删除元素只需要改变节点之间的指针链接,时间复杂度为O(1)。
-
空间占用:顺序表在创建时需要预先分配一定空间,而链表可以根据需要动态分配内存,因此可以节省空间。
-
访问效率:顺序表的元素在内存中连续存储,可以通过下标直接访问元素,因此访问效率较高。而链表需要通过指针从头节点开始逐个遍历,访问效率较低。
-
扩展性:顺序表的存储空间固定,如果空间不足需要扩容,需要重新申请更大空间,然后将原数据复制到新空间中。而链表的存储空间动态分配,可以灵活地扩展和收缩。
2.TCP/IP的三次握手和四次挥手(TCP/IP为什么是三次握手)
答:1. 客户端向服务器发送一个连接请求报文段。
-
服务器收到客户端发送的请求后,向客户端回复确认请求。
-
客户端收到服务器发送请求后,向服务器发送一个确认消息。
参考答案:
三次握手的目的是确保双方都能够正常发送和接收数据,建立可靠的通信连接。其过程如下:
-
客户端向服务器发送一个带有SYN(SYNchronization)标志位的连接请求报文段(SYN包)。
-
服务器收到客户端发送的SYN包后,向客户端回复一个带有SYN和ACK(ACKnowledgment)标志位的确认报文段(SYN+ACK包)。
-
客户端收到服务器发送的SYN+ACK包后,向服务器发送一个带有ACK标志位的确认报文段(ACK包)。
通过这样的握手方式,双方都能确保对方能够正常接收和发送数据,并且双方都确认了对方的可靠性。
四次挥手(four-way handshake)是TCP/IP协议中用于关闭连接的过程。它的过程如下:
-
客户端发送一个带有FIN(Finishing)标志位的报文段(FIN包)给服务器,请求关闭连接。
-
服务器接收到客户端发送的FIN包后,回复一个带有ACK标志位的确认报文段(ACK包)给客户端,表示收到了客户端的关闭请求。
-
服务器回复一个带有FIN标志位的报文段(FIN包)给客户端,告诉客户端自己也准备关闭连接。
-
客户端接收到服务器发送的FIN包后,回复一个带有ACK标志位的确认报文段(ACK包)给服务器,表示知道服务器准备关闭连接,并确认自己也准备关闭连接。
通过这个过程,双方都能够逐步关闭连接,并确保对方知道自己的准备状态。
为什么需要三次握手呢?主要有两个原因:
-
确定双方都具备发送和接收数据的能力:在第一次握手时,客户端向服务器发送了一个SYN包,服务器收到后回复了一个SYN+ACK包,表示服务器具备发送和接收数据的能力。然而,服务器不能确定客户端是否真的具备发送和接收数据的能力,所以需要客户端发送一个ACK包来确认。这样才能确保双方都具备发送和接收数据的能力。
-
防止已失效的连接请求报文段再次出现并产生错误:假设在第一次握手后,在网络中发生了延迟的情况,客户端并没有收到服务器发送的SYN+ACK包,这时客户端会再次发送一个SYN包。如果服务器接收到了这个已失效的SYN包并建立了连接,那么可能会导致不同步的连接状态出现。通过三次握手,能够在客户端和服务器双方都确认连接建立前先确认对方是否收到过连接请求报文段。
综上所述,TCP/IP采用三次握手的方式是为了保证双方都具备发送和接收数据的能力,并防止已失效的连接请求报文段再次产生错误连接。
3.指针和指针变量的区别
答:指针是存储数据的内存地址,指针变量是一个声明的标识符,用于存储指针
参考答案:
- 定义:
-
指针:指针是一种特殊的变量类型,用于存储内存地址。
-
指针变量:指针变量是一个声明的标识符,用于存储指针。
- 存储的值:
-
指针:指针存储的是一个内存地址,即某个变量的地址。
-
指针变量:指针变量存储的是一个指针值,即一个内存地址。
- 数据类型:
-
指针:指针的类型是根据指向的对象类型决定的。例如,一个指向整型变量的指针的类型是`int*`。
-
指针变量:指针变量的类型是指针所指向对象的类型。例如,一个指向整型变量的指针变量的类型是`int*`。
4.共享内存和消息队列的优缺点
答:
参考答案:
共享内存的优点:
-
速度快:共享内存是直接在进程间共享内存区域,不需要数据的复制和传输,因此速度比较快。
-
数据量大:共享内存适用于需要传输大量数据的场景,因为不需要复制数据,所以可以减少数据传输的开销。
共享内存的缺点:
-
同步问题:多个进程同时访问共享内存时,需要自己实现同步机制,以避免数据的不一致或竞争条件的发生。
-
安全性问题:共享内存是直接对内存进行操作,需要确保不会出现非法访问或破坏数据结构的行为。
消息队列的优点:
-
解耦合:消息队列通过将消息发送到一个中间的队列中,可以解耦发送者和接收者,使得它们不需要直接依赖于对方的存在。
-
灵活性:消息队列可以提供不同的消息传递模式,例如点对点方式、发布/订阅方式等,可以根据需求选择不同的模式。
消息队列的缺点:
-
速度相对慢:相较于共享内存,消息队列的数据传输需要经过操作系统内核的介入,因此传输速度相对较慢。
-
数据量限制:不同的操作系统对消息队列的大小都有一定的限制,不能传输过大的数据。
-
额外开销:使用消息队列需要额外的内核开销,例如队列的管理和操作系统的调度等。
5.结构体中一个char和一个int结构体中结构体的长度是多少
答:8,char 1字节, int 4字节,