一、C语言技术点
1、描述一下gcc的编译过程?
gcc编译分为四个阶段:预处理 编译 汇编 链接。
预处理:头文件包含、宏替换、条件编译、删除注释。
编译:主要进行词法、语法、语义分析等,检查无误后将预处理好的文件编译成汇编文件。
汇编:将汇编文件转换成二进制目标文件。
链接:将项目中的各个二进制文件+所需要的库+启动代码链接成可执行文件
2、内存的最小存储单位以及内存的最小计量单位分别是?
内存的最小存储单位为二进制位,内存的最小计量单位为字节
3、#include<>与#include""的区别?
#include<>到系统指定目录寻找头文件,#include""先到项目所在目录寻找头文件,如果没有再到系统指定目录下寻找。
4、描述一下变量的命名规则
变量名有字母、数值、下划线组成,但不能以数值开头。
5、变量的声明与定义有啥区别?
声明变量不需要建立存储空间,变量的定义需要建立存储空间。
6、谈谈C语言中有符号和无符号的区别?
有符号:数据的最高位为符号位,0表示正数,1表示负数。
无符号:数据的最高位不是符号位,而是数据的一部分。
7、谈谈计算机中补码的意义?
统一了0的编码,将符号位与其他位统一处理,将减法运算转换成加法运算。
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、文件缓冲区刷新方式有几种
行刷新('\n')、满刷新、强制刷新(fflush)、关闭刷新
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、啥叫宏函数以及作用
在项目中,经常把一些短小而又频繁使用的函数写成宏函数,这是由于宏函数没有普通函数参数压栈、跳转、返回等的开销,可以提高程序的效率。宏通过使用参数,可以创建外形和作用都与函数类似地类函数宏,宏的参数也用圆括号括起来,来保证宏函数的完整性。
28、如何理解库函数
库是已经写好的、成熟的、可复用的代码。每个程序都需要依赖很多底层库,不可能每个人的代码从零开始编写代码,因此库的存在具有非常重要的意义。在我们的开发应用中经常有一些公共代码是需要反复使用的,就把这些代码编译成库文件。库可以简单看成一组目标文件的集合,将这些目标文件经过压缩打包之后形成的一个文件。像windows这样的平台上,最常用的C语言库是由集成按开发环境所附带的运行库,这些库一般由编译厂商提供。