必考必会 | c语⾔技术点

c语⾔技术点

1. 描述一下 gcc 的编译过程?

  • gcc 编译过程主要分为 4 个阶段:预处理,编译,汇编,链接

    • 预处理:头文件包含,弘替换,条件编译,删除注释;
    • 编译:主要进行词法,语法,语义分析等,检查无误后将预处理好的文件汇编成汇编文件;
    • 汇编:将汇编文件转化成二进制目标文件;
    • 链接:将项目中的各个二进制文件+所需的库+启动代码链接成可执行文件。

2. 内存的最小单位以及内存的最小计量单位分别是

  • 内存的最小储存单位为 二进制位
  • 内存的最小计量单位 字节

3. #include<> 与 #include“” 的区别

  • include<> 到 系统指定目录 寻找头文件
  • include“” 先到 项目所在目录 寻找头文件,如何没有找到再到系统指定的目录下寻找

4. 描述一下变量的命名规则

  • 变量名由字母,数值,下划线组成,但不能以数值开头

5. 变量的声明与定义

  • 声明变量 不需要 建立储存空间
  • 变量的定义 需要 建立储存空间

6.谈谈 c 语言中有符号和无符号的区别

  • 有符号:数据的最高位为符号位,0 表示 正数,1 表示 负数
  • 数据的最高位不是符号位,而是数据的一部份

7. 谈谈计算机中补码的意义

  • 统一了零的编码
  • 将符号位与其他位统一处理
  • 将减法运算转化成加法运算

8. 谈谈数组的特点

  • 同一个数组所有的成员都是相同的数据类型,同时所有成员在内存中的地址是连续的。

9. 数组的分类

  • 数据的主要分类是:静态数组,动态数组两类。
    • 静态数组:类似 int arr[5]; 在程序运行时就确定了数组的大小,运行过程不能更改数组的大小;
    • 动态数组:主要是在堆栈中申请的空间,数组的大小是在程序运行过程中确定,可以更改数组的大小。

10. 描述一下一维数组的不初始化,部分初始化,完全初始化的不同点

  • 不初始化:如果是局部变量,数组元素的内容随机;如果是全局数组,数组的元素内容为 0
  • 部分初始化:未被初始化的部分自动补 0
  • 完全初始化:如果一个数组全部初始化,可以省略元素的个数,数组的大小有初始化的个数确定

11. 谈谈数组名作为类型,作为地址,对数组名取地址的区别

  • 数组名作为类型:代表的是整个数组的大小
  • 数组名作地址:代表是数组首元素的地址
  • 对数组名取地址:代表的是数组的首地址

12. 谈谈你对二维数组在物理上以及逻辑上的数组维度理解

  • 二维数组在逻辑上是二维的,在物理上是一维的

13. 描述一下函数的定义与函数的声明的区别

  • 函数定义:是指对函数功能的确立,包括指定函数名,函数类型,形参及其类型,函数体等。它是一个完整的,独立的函数单位。
  • 函数的声明:是指函数的名字,函数类型以及形参的个数,类型和顺序(不包括函数体)通知编译系统,以便在对包含函数调用的语句进行编译是,据此对其进行对照检查(例如函数名是否正确,实参与形参的类型和个数是否一样)

14. 描述一个指针与指针变量的区别

  • 指针:内存中每一个字节都会分配一个 32 位或 64 位的编号,这个编号就是地址,而指针就是内存单元的编号。
  • 指针变量:本质是变量,只是该变量存放的是空间的地址编码。

15. 描述一下 32 位或是 64 位平台下指针的大小

  • 32 位平台:任意类型的指针大小为 4 字节
  • 64 位平台:任意类型的指针大小为 8 字节

16. 描述一下指针数组的概念

  • 指针数组本质是数组,只是数组的每个元素是一个指针(地址)

17. 描述一下普通局部变量,普通全局变量,静态局部变量,静态全局变量的区别

  • 普通局部变量:存在栈区,不初始化随即内容,只在定义所在的复合语言中有效,符合语句结束变量空间释放
  • 普通全局变量:存在全局区,不初始化内容为 0,进程结束空间才被释放,能被当前源文件或是其他源文件使用,只是其他源文件使用的时候,要加 extern 修饰
  • 静态局部变量:存在全局区,不初始化内容为 0,整个进程结束空间才被释放,只能在定义所在的复合词句中有效
  • 静态全局变量:存在全局区,不初始化内容为 0 ,整个进程结束空间才被释放,只能被当前源文件使用

18. 描述一下内存分区

  • 程序在运行前:分为代码区, BSS 段(未初始化数据区),data段(初始化数据区)
  • 程序在运行后:堆区,栈区,全局区(静态区),文字常量区,代码区

19. 在使用 realloc 给已分配的推区空间追加空间时需要注意啥

  • 记得用指针变量保存 realloc 的返回值

20. 结构体与共用体的区别是啥

  • 结构体中的成员拥有独立的空间,共用体的成员共享一块空间,但是每个共用体成员能访问共用区的空间大小是有成员自身的类型决定。

21. 谈谈文件的分类

  • 文件分为二进制和文本文件
  • 二进制文件基于值编码,需要根据具体的应用才能知道某个值具体的含义
  • 文本文件基于字符编码,一个字节一个意思,可以通过记事本打开

22. 文件缓冲区刷新方式有几种

  • 行刷新,满刷新,强制刷新,关闭刷新

23. 那些情况下会出现野指针

  • 指针变量未初始化,指针释放后未置空,指针操作超越变量作用域

24. 如何理解指针作为函数的 输入输出 特性

  • 输入特性:主调函数分配空间 被调函数使用该空间
  • 输出特性:被调用分配空间,主调函数使用该空间

25. 如何理解结构体的浅拷贝与深拷贝

  • 当结构体中有指针成员的时候容易出现浅拷贝与深拷贝问题
  • 浅拷贝就是,两个结构体变量的指针成员指向同一块堆栈空间,在各个结构体变量释放的时候会出现多次释放统一堆栈空间
  • 深拷贝就是,让两个结构体变量的指针成员分别指向不同的堆区空间,只是空间内容拷贝一份,这样在各个结构体变量释放的时候就不会出现多次释放同一段堆区空间的问题

26. 描述一下结构体对齐规则

  • (1) 数组成员对齐规则。第一个数组成员应该放在 offset 为 0 的地方。以后每个数组成员放在 offset 为 min (当前成员的大小,#pargama pack(n)) 整数倍的地方开始(比如 int 在 32 机器为 4 字节,#pargama pack(2),那么从 2 的倍数地方开始储存)。
  • (2) 结构体总的大小,也就是 sizeof 的结果,必须是 min (结构体内部最大成员,#pargama pack(n))的整数倍,不足要补齐。
  • (3) 结构体作为成员的对齐规则。如果一个结构体 B 里嵌套另一个结构体 A ,还是以最大成员类型的大小对齐,但是结构体 A 的起点为 A 内部最大成员的整数倍的地方。(struct B 里存有 struct A,A 里面有 char, int, double 等成员,那 A 应该从 8 的整数倍开始存储。) 结构体 A 中的成员的对齐规则仍满足原则 1,原则 2 。

27. 宏函数以及作用

  • 在项目中,经常把一些短小而又频繁使用的函数写成宏函数,这是由于宏函数没有普通函数参数压栈、跳转、返回等的开销,可以提高程序的效率。宏通过使用参数,可以创建外形和作用都与函数类似地类函数宏 (function-like macro)。宏的参数也用圆括号扩起来,来保证宏函数的完整性。

28. 如何理解函数库

  • 库是已经写好的,成熟的,可复用的代码。每个程序都需要依赖很多底层库,不可能每个人的代码从零开始编写代码,应此库的存在具有非常重要的意义。在我们的开发的应用中经常有一些公共代码是需要反复使用的,这是编码译为库文件。库可以简单看成一组目标文件的集合,将这些目标文件经过压缩打包之后形成的一个文件。像 windows 这样的平台上,最常用的 c 语言库是由集成开发环境所附带的运行库,这些库一般由编译厂商提供。
C/C++面试必考必会 文章被收录于专栏

【C/C++面试必考必会】专栏,直击面试核心,精选C/C++及相关技术栈中面试官最爱的必考点!从基础语法到高级特性,从内存管理到多线程编程,再到算法与数据结构深度剖析,一网打尽。助你快速构建知识体系,轻松应对技术挑战。希望专栏能让你在面试中脱颖而出,成为技术岗的抢手人才。

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务