C开发面试题总结(持续更新中......)

因近期在进行面试,所以想着对过程中遇到的面试题进行记录,供大家进行参考。

C基础

  1. 一个程序相关的内容都会存储到区?局部变量和全局变量存储于哪个区?
    栈区:由编译器管理分配和回收,存放局部变量和函数参数。
    堆区:有程序员管理,需要手动 mallocfree 进行分配和回收,空间较大,但可能出现内存泄漏和空闲碎片的情况。
    全局/静态存储区:分为初始化和未初始化两个相邻区域,存储初始化和未初始化的全局变量和静态变量。
    常量存储区:存储常量,一般不允许修改。
    代码区:存放程序的二进制代码。

  2. 栈区和堆区有什么区别?
    :由编译器管理。需要时由编译器自动分配空间,不需要时自动回收,一般保存局部变量和函数参数等。内存空间连续,从高地址向低地址扩展,栈低高地址,空间较小。
    :由程序员管理,需要手动 mallocfree 进行分配和回收,如果未进行回收,将会造成内存泄露。不连续空间,其实系统内部由一个空闲链表。从低地址向高地址扩展,空间较大,较为灵活。

  3. 函数未定义会在预处理、编译、链接、执行哪个阶段发现?
    在链接阶段会检查出来。

  4. 宏展开是在哪个阶段?
    预处理

  5. static、const 关键字的作用及用法?
    static 控制变量的存储方式及可见性。主要作用有:修饰局部变量;修饰全局变量;修饰函数。
    const 控制对象不可被修改。主要作用有:修饰基本的数据类型;修饰指针变量;修饰函数入参。

  6. 介绍一下 fork()vfork() 函数?fork() 返回值都有什么,代表什么意思?
    fork()vfork() 是 Unix 和类 Unix 操作系统中用于创建新进程的系统调用。这两个函数的主要目的都是创建一个新的进程,但它们的实现和行为有所不同。
    fork() 函数用于创建一个新的进程,该新进程被称为子进程。子进程是父进程的一个复制品,拥有自己的地址空间、文件描述符等。返回值含义如下:
        子进程:fork() 在子进程中返回 0。
        父进程:fork() 在父进程中返回新创建的子进程的进程 ID(PID)。
        错误:如果 fork() 失败,它将返回 -1,并且设置 errno 来指示错误原因。
    vfork() 函数也是用于创建新进程,但它的实现方式不同。vfork() 在创建子进程时共享父进程的地址空间,直到调用 exec()exit()。这意味着在 vfork() 创建的子进程中,任何对父进程内存的修改都会影响到父进程。

  7. gdb 调试多进程,多线程命令?

	set detach-on-fork on	# 启用分叉时分离子进程
	set follow-fork-mode child	# 跟随子进程
	
	info threads	# 查看所有线程
	thread <id>	# 切换到指定线程
	info inferiors	# 查看所有进程
	inferior <id>	# 切换到指定进程
	
	break <function>	# 在函数设置断点
	continue	# 继续执行
	step	# 单步进入函数
	next	# 单步执行,不进入函数
	backtrace	# 查看当前线程的调用栈
	print <variable>	# 打印变量的值
	watch <variable>	# 观察变量的变化
	quit	#退出 GDB
  1. 对 flag 的某一位置零、置 1 ?
    置零是:flag = flag & ~(1 << n); ;置为 1:flag = flag | (1 << n);

  2. 内存对齐的规则是什么?为什么要内存对齐?
    对齐规则:
        对于结构体中的各个成员:第一个结构体成员位于偏移为 0 的位置,此后的每个结构体成员的偏移量都必须是 MIN(#pragma pack(X) , 结构体成员本身的类型长度) 的倍数(其中X的取值一般为 4 或 8 ,分别对应 32 位和 64 位操作系统)。
        所有结构体成员各自对齐之后,结构体本身也要进行对齐。结构体整体长度应该是 MIN(#pragma pack(X), 结构体中长度最长的结构体成员数据类型的长度) 的倍数。
    对齐原因:
        内存对齐可以提升 CPU 的性能。因为 CPU 是按块去处理内存的,内存块的大小可以是 2、4、8、16 个字节,块的大小称为内存读取粒度。假设内存读取粒度为 4 ,CPU 从 0 字节开始的位置读取一个 4 字节的数据到寄存器中,那么 CPU 将会把 0 ~ 3 四个字节全部读取到寄存器中进行处理。若数据起点位置不在 0 字节呢?假设数据起始位置为 2 字节,那么读取这个数据就需要 CPU 读取两次,首先读取 0 ~ 3,接着再读取 4 ~ 7,然后再把 0、1、6、7 字节的数据去除,最后合并 2、3、4、5 字节的数据放入寄存器中。上述就是内存未对齐的场景,此场景下寄存器做了很多额外的操作,必然会影响到 CPU 的性能。可参考:内存对齐总结

  3. 讲讲大小端,如何确定一台机器是大端还是小端?
    大端模式:数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址端。
    小端模式:数据的高字节保存在内存的高地址中,而低字节保存在内存的低地址端。
    检测方式:直接读取存放在内存中的十六进制数值,取低位进行值判断如下:

	int a = 0x12345678;
	unsigned char *a_ptr = (unsigned char *)&a;
	a_ptr[0] == 0x12;	// 大端模式
	a_ptr[0] == 0x78;	// 小端模式
  1. 设置地址 0x67a9 的整型变量值为 0xaa66 ?
	int *ptr;
	ptr = (int *)0x67a9;
	*ptr = 0xaa66;
  1. <

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

aSimpleSheep

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值