【面试】嵌入式C语言题目整理
- 描述内存四区。
内存四区分为:代码区、静态区、堆区、栈区
代码区就是用来存放代码的。
静态区用来存放全局变量、静态变量、常量(字符串常量、const修饰的全局变量)。
堆区中的内存是由程序员自己申请和释放的,用malloc函数去申请,用free释放内存。
栈区中的内存是由编译器自动申请和释放的,用来存放函数返回值、函数参数、局部变量等。
- new和malloc的区别
new和malloc都是用于动态的内存分配。
new是适用于C++申请内存分配,malloc在C和C++中都适用。
new自动计算分配内存大小,malloc需要手动计算内存大小,并以参数形态传入。也就是所new是根据类型申请的空间,malloc是根据输入的大小计算的内存空间。
new返回值是申请类型的指针,malloc返回类型是void*,需要强制转换。
- 数组与指针的区别
类型不同:数组是一种复合类型,它是由相同数据类型的元素组成的序列;指针是一种基本类型,它是一个指向某种类型地址的变量。
大小不同:如果用sizeof去求解占用内存大小的话,数组是全部元素实际占用的内存大小;而指针占用内存的大小与其指向类型无关,是固定的,例如在32位平台下,是固定的4字节。
内存布局不同:数组是一段连续的内存地址空间,而指针是指向某个存储位置的变量。
访问方式不同:数组可以通过下标来访问其中的元素,数组名可以当作指针使用,通过加加减减以及解引用的方式访问元素。
- static关键字
静态局部变量:只有当该变量所在的函数第一次被调用的时候,静态局部变量才会被初始化;当以后在进入该函数时,该变量不会再被初始化,仍旧保留上一次退出该函数时的值。
静态全局变量:只能被初始化一次,并且该变量的作用域只能是当前c文件。
静态函数:该函数只能被当前c文件调用,不可以被其他文件调用。
- gcc的编译过程
预处理、编译、汇编、链接
- 指针常量与常量指针
指针常量:int* const a; 该指针变量是不能变的,即存储的地址是不能变的,但是该地址指向的值是可以变化的。
常量指针:const int* a; 该指针变量是可以变化的,即存储的地址是可以变化的,但是地址指向的值是不能变化的。也就是说当a指向了一个地址之后,该地址中的值是不能通过a来改变的。
- #include<> 与#include ""的区别?
#include<>会去系统指定目录查找头文件。
#include ""会先在项目目录中查找头文件,如果没有的话,再去系统指定目录中查找。
- #define与typedef的区别
#define是预处理中的宏定义命令,在预处理阶段进行简单的字符替换,并不进行正确性检查。
typedef是关键字,常用于替换复杂类型声明定义
的简单别名,在编译阶段是进行正确性检查的。
#define不需要;结尾,typedef需要;结尾
这种定义方式,t和tt都是int*类型,而d和a是int*,dd和aa是int。
- ifndef/define/endif的作用
避免头文件被重复引用
- extern关键字
c语言在定义变量或者函数的时候,默认是前面加了extern关键字。
表明该变量或者函数能够被其他文件所使用。其他文件在使用的时候,需要用extern来声明所使用的变量或函数,表示该变量或函数需要去其他文件中查找。
- volatile关键字
volatile是c语言的关键字,作用是防止编译器被优化。
编译器优化的意思是,因为cpu的执行速度比内存的读取速度要快的多,某些变量可能会被存放在寄存器中,当cpu需要读取该变量时,就直接从寄存器读取(而不是去该变量的实际内存地址读取),提升了程序运行速度。
假如某个函数将该变量的值改变了,但是并未触发寄存器更新,那么cpu读取出来的值与实际值就会发生不一致。
所以需要vloatile关键字修饰变量,禁止编译器对其进行优化。
比如说:
中断服务程序中修改的供其它程序检测的变量需要加volatile。
被多个线程共享的变量需要加volatile。
- sizeof和strlen的区别
sizeof是关键字;strlen是函数
sizeof可以计算任何类型的实际内存占用大小;strlen只能计算字符串的实际长度。
sizeof是在编译时计算大小的;strlen是在运行期确定字符串长度的。