【C语言】C语言高频面试题

x. #define 和 const
#define const 都可以用于定义常量但以下区别(生效时间,内存占用情况,类型检查)
1.define只是单纯的文本替换, define常量的生命生命周期止于编译器, 不存在分配内存, 存在于程序的代码段
2.const 生效于编译的阶段; define 生效于预处理阶段
3.const 修饰的常量处于程序的数据段, 在堆栈中分配空间
4.const 有数据类型检查, define 没有
5.#define 不可调试, const 能调试
6.const 定义的变量在C中不是真正的常量
7.const 定义的常量不能作为数组的大小
x. typedefdefine (原理、作用域,对指针操作不同)
原理不同:
1.首先 #define 是预处理命令,在预处理阶段只是机械的替换带入字符串,并不会做类型检查,
2.typedef 是关键字,作用是给自己的作用域内给一个已经存在的类型起个别名
3.#define 没有作用域的限制,只要是之前预定义过的宏,在以后的程序中都可以使用,而 typedef 有自己的作用域
4.对指针的操作不同
比如: #define intper int *
	 typedef int * pre

intper p,q;   // 表示定义指针变量p和普通变量q
pre p,q;   // 表示定义指针变量p和指针变量q
所以在定义多个指针的时候就不是很方便
const intper p;  // 表示常量指针----->指针指向地址的内容不能改变
const pre p;   // 表示指针常量 
x. #include<头文件> 与 #include "头文件" 的区别

对于.#include<头文件>,表示是系统文件,编译会先从标准库路径下搜索,
编译器设置的头文件路径-->系统变量
对于#include "头文件",当前头文件目录-->编译器设置的头文件路径-->系统变量

对于编译速度来说:
语句#include < stdlib.h >是正确的,而且程序编译速度比#include "stdlib.h" 要快
    
解释:因为 stdlib.h 是系统文件,所以存放在系统的默认位置,所以,当#include< stdlib.h > 这样时就表示先去系统默认路径下查找,这样就很快找到stdlib.h
	如果#include"stdlib.h" 这样的的话,就会现在当前目录下找,但是没有这个文件,还得去默认路径找,所以如果是系统文件的话一般是使用 <>,自定义文件的话 ""
const 的作用
 1、对变量声明只读特性,保护变量值以防被修改。

 2、节省空间,避免不必要的内存分配。const修饰的变量在程序运行过程中只有一份拷贝。

 3、提高程序运行效率。编译器不为普通 const 常量分配存储空间,而是将他们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储和读取内存的操作。
volatile 作用
1. 告诉compiler不能做任何优化
2.volatile定义的变量会在程序外被改变,每次都必须从内存中读取,而不能重复使用放在cache或寄存器中的备份
使用 volatile 的场境
1. 中断服务程序中修改的供其它程序检测的变量需要加volatile
2. 多任务环境下各任务间共享的标志应该加volatile
3. 存储器映射的硬件寄存器通常也要加voliate,因为每次对它的读写都可能有不同意义
16.const 和 define 区别
1. 两者都可以定义常量
2. const 会进行类型检查
3. const 可以进行调试
4. const 是在编译期,define是在预处理
5. const 常量分配存在于数据段,分配内存,define 不会分配内存
x. 指针和数组的异同
指针和数组在C语言中具有一些相同点和不同点。

相同点:

1. 都可以用来存储和访问数据。
2. 都可以通过下标来访问元素。
3. 都可以作为函数的参数传递。

不同点:

1. 存储方式:数组是一组相同类型的元素按连续内存地址存储的集合,而指针只是一个变量,存储着一个内存地址。
2. 大小和长度:数组在定义时需要指定大小,且大小是固定的,不可改变。而指针没有固定大小,它只是存储一个内存地址。
3. 内容访问:通过数组名可以直接访问数组中的元素,而指针需要通过解引用操作符`*`来访问指针所指向的内存位置的内容。
4. 运算操作:数组名不能进行运算操作,而指针可以进行多种运算操作,如指针加减、比较、赋值等。
5. 关系:数组名可以被解释为指向数组首元素的指针,但是数组名不可修改,而指针可以指向其他位置。

	总的来说,指针和数组在某些方面有相似的功能,但在内存管理、访问方式和运算操作等方面有明显的差异。理解它们的共同点和不同点有助于正确使用它们以及更好地理解和设计C语言程序。
1. 网络编程如何解决粘包问题
	网络编程中的粘包问题指的是发送方在传输数据时,由于发送频率过快或者数据包过大,导致接收方无法准确地区分和解析每个数据包,从而导致数据粘连在一起的问题。

以下是一些常见的解决粘包问题的方法:

1. 数据长度固定:发送方在发送数据包之前,在数据包中添加固定长度的头部信息,表示数据包的长度。接收方首先根据头部信息获取到数据包的长度,然后按照相应长度读取数据,这样就可以正确地分离出每个数据包。

2. 特殊分隔符:发送方在数据包之间添加特定的分隔符,例如换行符、制表符等。接收方通过搜索分隔符,将接收到的数据分割成独立的数据包。

3. 定长包头:在数据包的头部添加固定长度的包头信息,包头信息中包含了数据包的长度等信息。接收方首先读取包头信息,并根据包头中的长度信息来接收数据包。

4. 使用消息队列:发送方将数据包发送到消息队列中,接收方从消息队列中依次获取数据包并处理。通过消息队列的单线程消费特性,保证了每个数据包独立处理,避免了粘包问题。

5. 序列化与反序列化:将数据包序列化成特定格式(如JSON、XML等),发送方在传输之前将每个数据包进行序列化,接收方在接收到数据后进行反序列化操作,这样可以准确地还原每个数据包。

以上方法可以根据具体需求和实际情况选择合适的解决方案。在实际应用中,通常会综合使用多种方法来解决粘包问题。
2. socket 如何解决断点续传问题
在网络编程中,通过 Socket 连接进行文件传输时,可以使用以下方法来解决断点续传问题:

1. 断点记录:发送方和接收方都记录传输的断点信息。发送方在发送数据之前,记录已经发送的字节数或者文件的偏移量;接收方在接收数据之前,记录已经接收的字节数或者文件的偏移量。这样,在出现传输中断的情况下,可以根据记录的断点信息进行续传。

2. Range 请求头:发送方和接收方支持 HTTP 的 Range 请求头。当发送方需要续传时,可以在请求头中指定文件的起始位置(Range: bytes=start-end);接收方根据请求头中的范围,只接收指定范围内的数据。这样,在续传时,只需传输断点之后的数据,避免重复传输已经传输过的数据。

3. 分块传输:将文件分成多个固定大小的块,每次传输一个块。发送方按顺序发送块,并携带块的序号信息;接收方根据接收到的块的序号,将每个块按序保存到本地。当传输中断时,可以根据已经接收到的块的序号,确定下一个待接收的块,从而实现断点续传。

4. 文件校验:在传输文件的过程中,发送方可以通过计算文件的校验值(如 MD5、SHA-1 等),并将校验值随数据一起发送给接收方。接收方在接收文件后,同样计算文件的校验值,并与发送方的校验值进行比对。如果校验值不匹配,则说明文件传输不完整或者存在错误,需要进行续传。

	以上方法可以根据具体需求和实际情况选择合适的解决方案。在实际应用中,通常会综合使用多种方法来实现可靠的断点续传功能。
3. 三次握手、四次挥手如何实现
TCP 是面向连接的可靠传输协议,建立和终止连接时采用了三次握手和四次挥手的机制。

三次握手的过程如下:

1. 客户端发送一个 SYN 报文,表示要建立连接,并指定自己的初始序列号 ISN。
2. 服务器收到 SYN 报文后,确认收到请求并发送一个 SYN+ACK 报文作为响应,其中 SYN 标志位用于表示确认连接请求,ACK 标志位用于表示确认客户端的初始序列号。同时,服务器也会指定自己的初始序列号 ISN2。
3. 客户端收到 SYN+ACK 报文后,向服务器发送一个 ACK 报文,其中 ACK 标志位表示确认服务器的初始序列号。此时,TCP 连接已经建立。

四次挥手的过程如下:

1. 客户端发送一个 FIN 报文,表示要关闭连接。
2. 服务器收到 FIN 报文后,发回一个 ACK 报文,确认收到客户端的请求,但暂时还不能关闭连接。
3. 当服务器准备好关闭连接时,向客户端发送一个 FIN 报文,表示可以关闭连接了。
4. 客户端收到 FIN 报文后,发回一个 ACK 报文确认收到关闭请求,并进入 TIME_WAIT 状态,等待一段时间后彻底关闭连接。服务器收到客户端的 ACK 报文后,进入 CLOSED 状态,连接断开。

	三次握手和四次挥手的机制保证了 TCP 连接的可靠性和正确性,并避免了不必要的数据重传或丢失。在实际应用中,通常也会根据具体需求和实际情况进行相应的优化和调整。
4. 多路复用 select、poll 和 epoll 的功能和区别
select、poll 和 epoll 都是在网络编程中用于实现 I/O 多路复用的机制,可以同时监视多个文件描述符,以便在有数据可读或可写时进行相应的处理。它们的功能和区别如下:

1. select:
- 功能:select 是最早出现的多路复用函数,可以同时监视多个文件描述符,并在其中任何一个文件描述符就绪时返回。
- 应用范围:select 在所有平台上都可使用,但在较大规模的连接数情况下性能较差。
- 缺点:每次调用 select 都需要将文件描述符集合从用户空间拷贝到内核空间,因此效率低下。同时,select 的文件描述符数量存在限制,通常默认为 10242. poll:
- 功能:poll 是对 select 的改进,同样可以同时监视多个文件描述符,并在就绪时返回。
- 应用范围:poll 在所有平台上也都可使用,性能相对于 select 有所提升,但在较大规模的连接数情况下仍然存在性能瓶颈。
- 缺点:与 select 类似,每次调用 poll 都需要将文件描述符数组从用户空间拷贝到内核空间,效率仍然不高。

3. epoll:
- 功能:epoll 是 Linux 特有的多路复用函数,通过内核与用户空间共享内存的方式避免了每次拷贝文件描述符数组的开销。它使用事件驱动的方式,将就绪的文件描述符放入就绪队列中,用户空间通过读取就绪队列获取事件。
- 应用范围:epoll 只能在支持 epoll 的 Linux 系统上使用,但在大规模连接数情况下有较好的性能表现。
- 优点:相较于 select 和 poll,epoll 的效率更高,可以同时监视大量的文件描述符,且没有数量限制。
- 差异点:
  - 模型:select 和 poll 都是水平触发(Level Triggered)模式,而 epoll 则可以选择水平触发或边缘触发(Edge Triggered)模式。
  - 监视方式:select 和 poll 需要遍历整个文件描述符集合,而 epoll 通过回调机制只返回已就绪的文件描述符,减少了系统调用的开销。
  - 文件描述符管理:select 和 poll 的文件描述符集合由用户空间传递给内核,而 epoll 的文件描述符集合则由内核管理,减少了内存拷贝的次数。

综上所述,select、poll 和 epoll 都可以实现 I/O 多路复用,但 epoll 在性能上具有优势,并且提供了更多灵活的操作方式和更高效的事件通知机制。因此,在 Linux 平台上,推荐使用 epoll 来进行高效的网络编程。
x. TCP 和 UDP 的异同点
TCP(传输控制协议)和UDP(用户数据报协议)是在网络通信中常用的两种传输协议,它们有以下的异同点:

相同点:
1. 都是在网络层和传输层之间提供可靠数据传输的协议。
2. 都可以在互联网上进行数据传输。
3. 都使用IP协议进行寻址和路由。

不同点:
1. 连接性:TCP是面向连接的协议,通过三次握手建立连接,然后进行数据传输,最后通过四次挥手断开连接。而UDP是无连接的协议,发送方直接发送数据包,不需要事先建立连接和拆除连接。
2. 可靠性:TCP提供可靠的数据传输,保证数据的顺序、完整性和可靠性,并支持重传机制以确保数据的正确性。而UDP不提供可靠性保证,不保证数据的可靠传输,可能出现丢包、乱序和重复等情况。
3. 通信效率:由于TCP提供了可靠性保证,需要进行连接的建立和维护,以及数据的确认和重传等额外开销,因此TCP的通信效率相对较低。而UDP不需要这些额外的开销,因此通信效率较高。
4. 数据顺序:TCP保证数据按照发送顺序接收,不会丢失和重复,因此数据是有序的。而UDP不保证数据的顺序性,可能出现乱序的情况。
5. 数据量限制:TCP对数据的长度没有明确的限制,可以适应大规模数据传输。而UDP对单个数据包的长度有限制,最大只能达到64KB。
6. 应用场景:由于TCP的可靠性和顺序性,适用于需要可靠传输的应用,如文件传输、电子邮件等。而UDP的高效性适用于实时性要求较高的应用,如音视频传输、实时游戏等。

总的来说,TCP和UDP具有不同的特点和适用场景,根据具体需求选择合适的协议进行网络通信。
x. 线程与进程的区别
进程和线程都是操作系统中用于实现并发执行的基本单位,它们之间的区别如下:

1.定义:进程是一个正在执行中的程序的实例,它拥有独立的地址空间、数据栈、文件和设备描述符等系统资源。而线程是操作系统调度的最小执行单位,它与所属进程共享进程的地址空间和系统资源。

2.资源占用:每个进程都有独立的系统资源,如文件描述符、网络连接、内存空间等,而线程只占用其所属进程的系统资源。

3.创建开销:由于进程的独立性和隔离性,创建一个新进程的开销比较大,需要为之分配独立的资源和地址空间。而线程共享所属进程的资源,因此创建一个新线程的开销相对较小。

4.通信和同步:进程之间的通信和同步需要使用特殊的机制,如管道、消息队列、共享内存等。而线程之间的通信和同步比较容易,可以通过共享内存或全局变量进行通信,使用信号量、互斥锁等同步机制。

5.错误隔离:一个进程的错误不会影响其他进程,因为它们拥有独立的地址空间和资源。但是一个线程的错误可能导致整个进程的崩溃。

6.上下文切换:由于线程共享进程的地址空间,线程之间的上下文切换开销相对较小。而进程之间的上下文切换需要切换地址空间,开销相对较大。

	总的来说,进程是资源分配的基本单位,线程是执行调度的基本单位。进程具有较高的隔离性和稳定性,而线程具有较低的创建开销和较好的并发性能。在设计和实现并发程序时,可以根据具体需求选择合适的进程和线程来进行处理。
说说软链接和硬链接的区别
Linux中的软连接(Symbolic Link)和硬链接(Hard Link)是文件系统中常用的链接方式,它们的主要区别如下:

1. 文件类型:软连接是一个特殊类型的文件,而硬链接是一个指向文件索引节点的目录项。

2. 文件大小:软连接文件本身有自己的文件大小,而硬链接文件和源文件共享相同的磁盘空间,它们的大小统计上是一样的。

3. 跨文件系统:软连接可以跨越不同的文件系统,而硬链接只能在同一文件系统内创建。

4. 原理:软连接是通过创建一个新的文件来指向源文件,该新文件保存了源文件的路径信息。而硬链接则是创建一个源文件的新目录项,包含相同的索引节点信息。

5. 对源文件的依赖性:软连接是依赖于源文件存在的,如果源文件被删除了,软连接会失效;而硬链接与源文件是完全独立的,即使源文件被删除,硬链接仍然存在。

6. 目标对象:软连接可以链接到文件或目录,而硬链接只能链接到文件。

7. 修改:对软连接的修改会影响到源文件,而对硬链接的修改不会影响到源文件。

	总的来说,软连接更加灵活,可以跨越文件系统,但是对源文件的依赖性较高;而硬链接在同一文件系统内非常稳定,对源文件的依赖性较低。在使用时,可以根据具体需求选择适当的链接方式。
静态库 和 动态库 的区别
1)静态库代码装载的速度快,执行速度略比动态库快。
2)动态库更加节省内存,可执行文件体积比静态库小很多。
3)静态库是在编译时加载,动态库是在运行时加载。
4)生成的静态链接库,Windows下以.lib为后缀,Linux下以.a为后缀。生成的动态链接库,Windows下以.dll为后缀,Linux下以.so为后缀
标准IO 和 系统IO 的区别
标准I/O(Standard I/O)和系统I/O(System I/O)是操作系统中用于进行输入和输出操作的两种不同方式,它们之间的区别如下:

1. 缓冲机制:标准I/O使用缓冲机制,数据先被读入到缓冲区,然后再从缓冲区进行读取或写入操作。而系统I/O直接将数据从文件或设备读入到用户空间,或将数据从用户空间写入到文件或设备,没有额外的缓冲层。

2. 数据传输方式:标准I/O是按行进行数据读取或写入操作,即以换行符为单位进行处理。而系统I/O则是以字节流的形式进行数据传输,没有特定的行结构。

3. 调用方式:标准I/O使用库函数进行调用,例如C语言中的`printf`和`scanf`等函数。而系统I/O使用系统调用(syscall)来进行直接的操作,例如`read`和`write`等系统调用。

4. 效率:由于标准I/O使用了缓冲机制,可以减少系统调用的次数,因此在大量数据的读写操作中,标准I/O通常比系统I/O具有更高的效率。但对于少量数据的读写操作,由于标准I/O需要额外的缓冲管理,可能会导致一定的性能损失。

	总的来说,标准I/O提供了更方便和高层次的接口,具备缓冲、行处理等功能,适用于大量数据的读写操作。而系统I/O则是直接操作文件和设备的底层接口,适用于对数据精确控制或少量数据的读写操作。在实际应用中,可以根据具体需求选择使用标准I/O或系统I/O来进行输入和输出操作。
OSI七层模型 和 TCP/IP四层模型
OSI七层模型(Open Systems Interconnection Reference Model)和四层模型是两种不同的网络协议参考模型,它们分别是:

1. OSI七层模型:
   - 物理层(Physical Layer):负责传输比特流,处理物理介质上的电压、电流等信号。
   - 数据链路层(Data Link Layer):负责将比特流组织成帧,在物理连接上提供可靠的数据传输。
   - 网络层(Network Layer):负责将数据在网络中进行路由选择和转发,实现不同网络之间的通信。
   - 传输层(Transport Layer):负责提供端到端的可靠数据传输和错误恢复,例如TCP和UDP协议。
   - 会话层(Session Layer):负责建立、管理和终止会话,提供会话控制功能。
   - 表示层(Presentation Layer):负责数据的表示、加密、压缩和格式转换等,提供数据格式的协商功能。
   - 应用层(Application Layer):通过应用程序提供服务,例如HTTP、FTP、SMTP等。

2. 四层模型(TCP/IP四层模型):
   - 网络接口层(Network Interface Layer):相当于物理层和数据链路层的组合,负责物理接口及网络设备驱动程序。
   - 网络层(Internet Layer):相当于网络层,负责IP地址的分配和路由选择,实现不同网络之间的通信。
   - 传输层(Transport Layer):相当于传输层,提供端到端的可靠数据传输和错误恢复,例如TCP和UDP协议。
   - 应用层(Application Layer):相当于会话层、表示层和应用层的组合,通过应用程序提供服务。

	与OSI七层模型相比,四层模型将会话层、表示层和物理层的功能进行了简化和合并,减少了层级,更加符合实际网络协议的实现。TCP/IP协议族是在四层模型基础上发展起来的,是互联网中最为广泛使用的网络协议。而OSI七层模型则提供了更为详细和全面的网络协议参考框架。
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值