嵌入式_复习

函数指针与指针函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

#include <stdio.h>

int add(int a, int b)
{
return a + b;
}

int* aaaaa(void) // 返回指针的函数就是指针函数
{
}

int main()
{
int (*ptr)(int, int) = &add; // 取函数的指针就是函数指针

int c = ptr(10, 20);

printf("%d\n", c);
}

指针大小

指针大小与操作系统的位数有关,32位指针大小是4个字节,64位指针大小是8个字节

1
2
3
4
5
6
7
int main()
{
char* a;
int* b;
float* c;
printf("%d, %d, %d\n", sizeof(a), sizeof(b), sizeof(c)); // 8, 8, 8
}

sizeof与strlen的区别

  • sizeof是一个运算符,strlen是一个函数,需要包含string.h头文件
  • sizeof计算的是所占内存的大小,strlen计算的是字符串的长度。字符串以\0结尾,\0是不需要计算长度的
  • sizeof可以计算其他类型int,float等,strlen一般用于字符串的长度
1
2
3
4
5
6
7
8
#include <stdio.h>
#include <string.h>


int main()
{
printf("%d, %d\n", sizeof("\0"), strlen("\0")); // 2, 0 因为sizeof里面的是字符串以\0结尾,所以有2个0,2个字符,所有是2个字节
}

C语言内存分配方式

  • 静态存储器分配,例如全局变量,静态变量。
  • 栈上分配,函数中定义的局部变量
  • 堆上分配,malloc, new

数组指针和指针数组

  • 数组指针指的是指向数组的指针,本质是一个指针
  • 指针数组本质是一个数组,里面的每个元素都是指针
1
2
3
4
5
6
7
8
9
int main()
{
int(*p)[10]; // 数组指针的申明

int *a, a1, a2;
int* p1[10] = { a, a1, a2 }; // 指针数组

// printf("%d, %d, %d\n", sizeof(a), sizeof(b), sizeof(c));
}

struct结构体和union联合体

  • union共享一块内存地址,大小 = 成员中占内存最大的成员的大小
  • 结构体不同成员放在不同的内存地址。大小 = 所有成员大小之和(字节对齐)

野指针

​ 野指针是指向不可用内存的指针

​ 当指针被创建的时候,没有赋值这个时候指针就成为了野指针

​ 当指针被free或者delete后如果没有把指针赋值为NULL,这个时候也是野指针

​ 当指针越界的时候也是野指针

数组和链表的区别

  • 数组的地址空间是连续的
  • 链表的地址空间是不连续的
  • 数组的访问速度比较快,数组直接通过下标就能访问,链表需要遍历
  • 链表增删改的速度比较快

define与typedef的区别

​ define是一个预处理指令,typedef是关键字

​ define不会做正确性检查,直接进行替换,typedef会做正确性检查

​ define没有作用域的限制,typedef有作用域的限制

Static的作用

​ 定义一个静态变量或者静态函数

​ 在函数中定义变量,变量只会初始化一次

​ 定义的静态变量或者函数只能在当前文件中使用,作用域的限制

​ 在函数内部定义的静态变量无法被其他函数使用

内存泄露

​ 内存泄露指的是在程序运行的时候,动态分配的空间没有被回收或者正常释放,导致这个内存空间还占据着系统资源

内存对齐

​ 内存对齐是在储存数据时,将数据按照一定的规则放置在内存中的过程

数组名和指针的区别

​ 数组名就是数组首元素的地址,也可以看做一个常量指针,这个是不能修改指向的

​ 使用指针访问数组的时候需要使用到解引用*,使用指针访问数组是间接访问,使用数组名访问数组是直接访问

​ 使用sizeof对指针和数组名进行计算的时候是不同的,指针的大小和编译器的位数有关,sizeof数组名是整个数组的大小

指针常量和常量指针

​ 常量指针是指向一个常量的指针,这个指针无法修改所指向的数据,但是可以修改指向

1
2
3
4
5
6
7
8
int main()
{
int a = 5;
int b = 6;
const int* p = &a;
p = &b; // 可以修改指向
// *p = 6; // 常量指针无法修改指向的数据
}

​ 指针常量是指针是一个常量,指针所指向的地址是固定的 ,但是可以修改地址中的值

1
2
3
4
5
6
int main()
{
int a = 5;
int* const p1 = &a;
*p1 = 6;
}

堆和栈的区别

​ 创建方式不同,栈是系统自动创建(栈主要用于保存局部变量),当函数执行完成,栈被销毁

​ 堆是程序员手动创建和释放的,malloc创建free释放

​ 空间大小的区别,栈的空间是比较小的,堆的空间是比较大的

​ 访问速度,栈的访问速度是比堆要快的

​ 生命周期,栈自动销毁,堆手动销毁

Malloc和new的区别

​ malloc是c语言中的标准库函数,new是c++中的操作符

​ malloc分配内存后返回的是void*类型的指针,new分配内存后返回的是对应对象类型的指针

​ 使用malloc分配内存的时候需要进行指定分配内存的大小,使用new进行内存分配时不需要制定

​ 使用malloc分配内存的时候不会调用构造函数,使用new分配内存时会调用到构造函数

struct和class在c++中的区别

​ struct成员默认是公有的,class默认的是私有的

​ 继承方面,struct默认的是公有继承,class默认的是私有继承

​ struct一般使用与简单的数据结构,class一般用于封装和继承

c++中的类有几个访问权限

​ 公有的,私有的,受保护的

程序分为几个段

​ 代码段,用于储存程序的可执行指令,一般是只读的,防止被修改

​ 数据段,用于储存已经初始化的全局变量和静态变量

​ bss段,储存没有初始化的全局变量和静态变量

​ 堆,malloc和free进行管理

​ 栈,储存局部变量,系统申请和释放

队列和栈的区别

​ 访问的方式,栈是先进后出,队列先进先出

​ 栈,只能在栈顶进行操作,队列,在队尾进行插入,在对头进行删除

​ 栈主要用于函数调用,表达式求值,队列,任务调度,广度优先搜索

c文件执行流程

​ 预处理,将头文件宏定义进行展开,生成没有注释的源代码,.i文件

​ 编译,将预处理得到的源代码转为汇编代码 .s文件

​ 汇编,将汇编代码转为机器码 生成 .o文件

​ 链接 ,将全部的.o文件链接为可执行程序

SPI和IIC的寻址区别

​ SPI MISO MOSI SCLK CS 通过cs线片选引脚,选择对应的设备进行通信

​ IIC SDA SCL 通过从机地址进行寻址7位和10位方式

进程间通信有几种方式,哪几种需要借助内核

​ 管道,命名管道,共享内存,信号量,消息队列,套接字,信号

什么是DMA

​ DMA是一种无需cpu参与就可以让外设和系统之间的数据进行双向数据传递,可以提高效率

进程有几个状态

​ 创建状态 当调用fork进入创建状态

​ 就绪状态

​ 运行状态

​ 阻塞状态

​ 终止状态

僵尸进程,孤儿进程,守护进程

​ 僵尸进程,使用fork子进程后,如果子进程退出,父进程并没有调用wait或者waitpid函数获取子进程的退出状态,那个子进程的信息还保存在系统中,这个时候子进程就叫做僵尸进程

​ 父进程异常结束,子进程就会变成孤儿进程,会被init1号进程收养

​ 在父进程创建出子进程后故意把父进程结束,那个这个子进程就是守护进程

FreeRTOS的调度算法

​ 抢占式调度,高优先级的任务可以打断低优先级任务的执行,适用于优先级不同的任务

​ 时间片轮转,相同优先级的任务具有相同大小的时间片

​ 协作式调度,让出cpu,通过信号量等切换任务

RTOS中任务同步的方式

​ 队列,信号量,互斥量,事件组,任务通知

FreeRTOS任务的状态

​ 就绪态,运行态,阻塞态,挂起态

RS232和RS485的区别

​ RS232是全双工通信,tx,rx,gnd

​ rs485是半双工通信 只有两根信号线。差分传输

​ 抗干扰能力,rs485抗干扰能力比rs232更强,使用双绞线将2根信号线缠绕在一起

​ rs232一般用于点对点通信,rs485多对多,一对多,工业控制

​ 485传输距离1.5km 232只有15m

​ 232传输速率比较低,485传输速率比较高

析构函数与构造函数

​ 构造函数,初始化对象,设定初始值, 没有返回值,多个重载版本

​ 析构函数 释放资源,清理操作,没有参数也没有返回值,不能重载

大小端

​ 多字节的数据在内存中的存储顺序方式,在不同的计算机中使用不同的字节序来表示数据

​ 大端储存,高字节在低地址,低字节在高地址

​ 小端存储,低字节在低地址,高字节在高地址

​ 0x12345678, 假设第一个字节是0x78,那么为小端存储,第一个字节为0x12,是大端存储

系统调用

​ 用户和内核之间的接口,通过接口可以使用用户空间访问到内核空间,直接访问内核空间是非常不安全的,导致内核崩溃

软件IIC和硬件IIC的区别

​ 软件,通过控制gpio来模拟scl和sda信号来产生iic的时序

​ 硬件,mcu内部的专用硬件模块来产生时序,软件只负责发出命令

Linux驱动分类

​ 字符设备驱动,用于处理顺序数据的读写操作,适用于终端,串口,led,蜂鸣器

​ 块设备驱动,主要用于处理以块为单位的数据读写操作,硬盘。ssd

​ 网络设备驱动,网卡设备

Linux与RTOS的区别

​ 应用场景,linux桌面计算机,服务器,嵌入式系统, rtos嵌入式系统

​ linux不保证实时性,rtos提供严格的实时性保证,任务的调度和执行时间非常可预测,任务的响应都非常快

​ linux占用资源多,rtos轻量级操作系统

​ linux有虚拟内存,内核空间和用户空间,rtos没有虚拟内存,也没有用户空间和内核空间

​ linux的扩展非常高

fork和vfork的区别