嵌入式秋招知识总结(一)
对CPU、寄存器、缓存、内存的大概了解:
一般市场上的CPU和寄存器、缓存封装出售,CPU每次都要在寄存器存取,寄存器是个临时存取空间,寄存器去访问CPU,在寄存器和CPU之间有个缓存(cache),将常用的数据存到缓存上,缓存有三级缓存(1、2、3),价格和速度依次降低。寄存器要获取的变量能不能在缓存中获取到就涉及到命中率问题,如果获取不到,就直接从内存去拿。
栈区:存放函数的参数值、局部变量等,由编译器自动分配和释放,通常在函数执行完后就释放了,其操作方式类似于数据结构中的栈。栈内存分配运算内置于CPU的指令集,效率很高,但是分配的内存量有限,比如iOS中栈区的大小是2M。
堆区:就是通过new、malloc、realloc分配的内存块,编译器不会负责它们的释放工作,需要用程序区释放。分配方式类似于数据结构中的链表。在iOS开发中所说的“内存泄漏”就是堆区的内存。
静态区:全局变量和静态变量(在iOS中就是用static修饰的局部变量或者是全局变量)的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后,由系统释放。
常量区:常量存储在这里,不允许修改。代码区:存放函数体的二进制代码。
类型说明符:类型说明符 void、char、short、int、long、signed、unsigned、float、double、struct、enum、union。存储类型 extern、static、register、auto、typedef(变量有且只能有一个限定)。类型限制符 const(只读)、volatile。
对变量的理解:
extern:用在全局变量上表示该变量在其他文件中已经定义;用在函数上作用同全局变量。
static:用在全局变量上,和非静态全局变量相比,限定了作用空间;用在局部变量上,把局部变量存到了静态存储区,延长了变量生存空间;用在函数上表示仅限当前文件使用。
register:将频繁使用的变量放到通用寄存器中,避免频繁访问内存,直接从寄存器中取值,提高CPU的工作效率;注:只能将局部变量或形式参数定义为寄存器变量,一般较短的变量类型适合定义为寄存器变量,如short、char等。
auto:C语言变量缺省存储类型就是auto。
typedef:给变量或变量表达式换一个别名。
const:只读变量;但是能通过指针去修改局部const变量,const变量是一个编译期间的常量。
volatile:
1. 易变性;所谓的易变性,在汇编层面反映出来,就是两条语句,下一条语句不会直接使用上一条语句对应的volatile变量的寄存器内容,而是重新从内存中读取。volatile的这个特性,相信也是大部分朋友所了解的特性。
2. “不可优化”特性。volatile告诉编译器,不要对我这个变量进行各种激进的优化,甚至将变量直接消除,保证程序员写在代码中的指令,一定会被执行。
3. C/C++ Volatile变量间的操作,是不会被编译器交换顺序的。(中断、多线程)。
C程序的内存分配:堆、栈、静态存储区、文件分配区(常量字符串)、程序分配区(二进制代码)。
sizeof与strlen:
sizeof是关键字,对于数组来说就是申请的长度,对于指针来说就是4/8(看系统位数)。
strlen对于字符串来说,就是计算‘\0’之前的长度。
函数的参数传递:值传递,引用传递,指针传递,数组地址传递。
Const、指针、int/char等组合的意义:
const int x:表示变量只读,不可更改。
const char * x/char const *x:声明该指针变量指向的是常量,即该指针变量的内容可以改变,但是该内容指向的内容不可改变;如:const char *x = “helloworld”;可以直接更改x,如x = ”hi“就可以成功,但更改x[0] = ‘u’就会失败。
char *const x:声明该指针变量为常变量,即指针变量里面的内容不可改变,但是该内容指向的内容可以改变;const char *x = “helloworld”;不可以直接更改x,如x = ”hi“会失败,但更改x[0] = ‘u’就会成功。
const char *const x:声明该指针变量里面的内容不可改变,同时该内容指向的内容亦不可改变。
数组和指针:
sizeof的用法,占用内存(连续\不确定),物理地址和逻辑地址。
物理地址:加载到内存地址寄存器的地址,内存单元的真正地址;逻辑地址:CPU所生成的地址。
Linux进程间通信:有几种方式:管道(pipe)、信号量、消息队列、信号、共享内存、套接字。
strcpy和memcpy区别:
strcpy只能复制字符串,memcpy能复制任何内容,memcpy会指定复制长度。
内存泄漏和内存溢出:
内存泄露是指申请的内存没有释放,导致可用内存越来越少;内存溢出指程序要用的内存大于可用的内存,如数组的使用,strcpy的使用。
switch的变量允许哪些类型?不允许哪些类型?
整形、bool、字符、枚举;不允许字符串等非基本类型。
怎么防止头文件重复调用导致的编译问题:
在头文件中添加#ifndef变量 /#pragma once。
实时操作系统有哪些?怎么理解?路由器用的什么操作系统?
FreeRTOS、Ucos。
指针数组和数组指针,双重指针:
对指针数组来说,首先它是一个数组,数组的元素都是指针,也就是说该数组存储的是指针,数组占多少个字节由数组本身决定;而对数组指针来说,首先它是一个指针,它指向一个数组,也就是说它是指向数组的指针,在32位系统下永远占4字节,至于它指向的数组占多少字节,这个不能够确定,要看具体情况。
指针数组如char *x[10],指向数组的指针,如char *x[10]={“hello”,“world”};x[0]=“hello”,x[1]=“world”。
数组指针如char (*x)[10],表示指针x指向char [10]数组,为匿名数组。
双重指针如char **x。
结构体自增的含义,双重指针自增:
自增从右向左进行。
寄存器怎么用,怎么操作?
保存一些经常调用的数据,不再访问内存。
怎么获取全局变量和局部变量的地址?(gdb)
backtrace bt。
进程中的同步、异步怎么用?
同步一般通过同步锁实现;同步锁和自旋锁区别:一种是没有获取到锁的线程就一直循环等待判断该资源是否已经释放锁,这种锁叫做自旋锁,它不用将线程阻塞起来(NON-BLOCKING);还有一种处理方式就是把自己阻塞起来,等待重新调度请求,这种叫做互斥锁。
进程和线程的关系和区别?
进程:进程是能在系统中独立运行并作为资源分配的基本单位,是CPU分配资源的最小单位,它包括独立的地址空间、资源以及一至多个线程。
线程:线程是进程中的一个实体,是CPU调度的最小单位。
树的遍历(递归&&非递归):
如利用中序遍历,左子树-根节点-右子树,根据堆栈的push和pop进行进栈和出栈的操作。
嵌入式C++面经推荐大佬面经 链接在下边
一般市场上的CPU和寄存器、缓存封装出售,CPU每次都要在寄存器存取,寄存器是个临时存取空间,寄存器去访问CPU,在寄存器和CPU之间有个缓存(cache),将常用的数据存到缓存上,缓存有三级缓存(1、2、3),价格和速度依次降低。寄存器要获取的变量能不能在缓存中获取到就涉及到命中率问题,如果获取不到,就直接从内存去拿。
栈区:存放函数的参数值、局部变量等,由编译器自动分配和释放,通常在函数执行完后就释放了,其操作方式类似于数据结构中的栈。栈内存分配运算内置于CPU的指令集,效率很高,但是分配的内存量有限,比如iOS中栈区的大小是2M。
堆区:就是通过new、malloc、realloc分配的内存块,编译器不会负责它们的释放工作,需要用程序区释放。分配方式类似于数据结构中的链表。在iOS开发中所说的“内存泄漏”就是堆区的内存。
静态区:全局变量和静态变量(在iOS中就是用static修饰的局部变量或者是全局变量)的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后,由系统释放。
常量区:常量存储在这里,不允许修改。代码区:存放函数体的二进制代码。
类型说明符:类型说明符 void、char、short、int、long、signed、unsigned、float、double、struct、enum、union。存储类型 extern、static、register、auto、typedef(变量有且只能有一个限定)。类型限制符 const(只读)、volatile。
对变量的理解:
extern:用在全局变量上表示该变量在其他文件中已经定义;用在函数上作用同全局变量。
static:用在全局变量上,和非静态全局变量相比,限定了作用空间;用在局部变量上,把局部变量存到了静态存储区,延长了变量生存空间;用在函数上表示仅限当前文件使用。
register:将频繁使用的变量放到通用寄存器中,避免频繁访问内存,直接从寄存器中取值,提高CPU的工作效率;注:只能将局部变量或形式参数定义为寄存器变量,一般较短的变量类型适合定义为寄存器变量,如short、char等。
auto:C语言变量缺省存储类型就是auto。
typedef:给变量或变量表达式换一个别名。
const:只读变量;但是能通过指针去修改局部const变量,const变量是一个编译期间的常量。
volatile:
1. 易变性;所谓的易变性,在汇编层面反映出来,就是两条语句,下一条语句不会直接使用上一条语句对应的volatile变量的寄存器内容,而是重新从内存中读取。volatile的这个特性,相信也是大部分朋友所了解的特性。
2. “不可优化”特性。volatile告诉编译器,不要对我这个变量进行各种激进的优化,甚至将变量直接消除,保证程序员写在代码中的指令,一定会被执行。
3. C/C++ Volatile变量间的操作,是不会被编译器交换顺序的。(中断、多线程)。
C程序的内存分配:堆、栈、静态存储区、文件分配区(常量字符串)、程序分配区(二进制代码)。
sizeof与strlen:
sizeof是关键字,对于数组来说就是申请的长度,对于指针来说就是4/8(看系统位数)。
strlen对于字符串来说,就是计算‘\0’之前的长度。
函数的参数传递:值传递,引用传递,指针传递,数组地址传递。
Const、指针、int/char等组合的意义:
const int x:表示变量只读,不可更改。
const char * x/char const *x:声明该指针变量指向的是常量,即该指针变量的内容可以改变,但是该内容指向的内容不可改变;如:const char *x = “helloworld”;可以直接更改x,如x = ”hi“就可以成功,但更改x[0] = ‘u’就会失败。
char *const x:声明该指针变量为常变量,即指针变量里面的内容不可改变,但是该内容指向的内容可以改变;const char *x = “helloworld”;不可以直接更改x,如x = ”hi“会失败,但更改x[0] = ‘u’就会成功。
const char *const x:声明该指针变量里面的内容不可改变,同时该内容指向的内容亦不可改变。
数组和指针:
sizeof的用法,占用内存(连续\不确定),物理地址和逻辑地址。
物理地址:加载到内存地址寄存器的地址,内存单元的真正地址;逻辑地址:CPU所生成的地址。
Linux进程间通信:有几种方式:管道(pipe)、信号量、消息队列、信号、共享内存、套接字。
strcpy和memcpy区别:
strcpy只能复制字符串,memcpy能复制任何内容,memcpy会指定复制长度。
内存泄漏和内存溢出:
内存泄露是指申请的内存没有释放,导致可用内存越来越少;内存溢出指程序要用的内存大于可用的内存,如数组的使用,strcpy的使用。
switch的变量允许哪些类型?不允许哪些类型?
整形、bool、字符、枚举;不允许字符串等非基本类型。
怎么防止头文件重复调用导致的编译问题:
在头文件中添加#ifndef变量 /#pragma once。
实时操作系统有哪些?怎么理解?路由器用的什么操作系统?
FreeRTOS、Ucos。
指针数组和数组指针,双重指针:
对指针数组来说,首先它是一个数组,数组的元素都是指针,也就是说该数组存储的是指针,数组占多少个字节由数组本身决定;而对数组指针来说,首先它是一个指针,它指向一个数组,也就是说它是指向数组的指针,在32位系统下永远占4字节,至于它指向的数组占多少字节,这个不能够确定,要看具体情况。
指针数组如char *x[10],指向数组的指针,如char *x[10]={“hello”,“world”};x[0]=“hello”,x[1]=“world”。
数组指针如char (*x)[10],表示指针x指向char [10]数组,为匿名数组。
双重指针如char **x。
结构体自增的含义,双重指针自增:
自增从右向左进行。
寄存器怎么用,怎么操作?
保存一些经常调用的数据,不再访问内存。
怎么获取全局变量和局部变量的地址?(gdb)
backtrace bt。
进程中的同步、异步怎么用?
同步一般通过同步锁实现;同步锁和自旋锁区别:一种是没有获取到锁的线程就一直循环等待判断该资源是否已经释放锁,这种锁叫做自旋锁,它不用将线程阻塞起来(NON-BLOCKING);还有一种处理方式就是把自己阻塞起来,等待重新调度请求,这种叫做互斥锁。
进程和线程的关系和区别?
进程:进程是能在系统中独立运行并作为资源分配的基本单位,是CPU分配资源的最小单位,它包括独立的地址空间、资源以及一至多个线程。
线程:线程是进程中的一个实体,是CPU调度的最小单位。
树的遍历(递归&&非递归):
如利用中序遍历,左子树-根节点-右子树,根据堆栈的push和pop进行进栈和出栈的操作。
嵌入式C++面经推荐大佬面经 链接在下边
c++/嵌入式面经专栏-牛客网
https://gw-c.nowcoder.com/api/sparta/jump/link?link=https%3A%2F%2Fwww.nowcoder.com%2Fcreation%2Fmanager%2FcolumnDetail%2FMJNwoM
全部评论
相关推荐
查看9道真题和解析
点赞 评论 收藏
分享
查看31道真题和解析
点赞 评论 收藏
分享
点赞 评论 收藏
分享