volatile
容易发生变化的。对于单片机编程而言,通常用来修饰状态寄存器,确保状态寄存器在被读到时是最新的值。作用原理是告诉编译器,这个寄存器使用的时候必须去外设中去取最新的值,不要优化操作。
static
静态的。顾名思义,不容易发生变化。常用语限制全局变量或者函数的作用域。或者让局部变量保存到全局变量区,变量值在函数调用结束后不会释放。
内联函数
关键字,inline;
- 作用是减少内部调用函数入栈出栈的过程,加快程序运行。
- 作用机理就是将代码直接拷贝过去,然后编译,用内存空间来换取时间。
- 应用场景,for 循环连续调用一个函数时使用这个关键字连减少反复的入栈和出栈的时间。在core_cm3.h中通常会有定义。
- 使用条件:
– 1、被调用函数要简单;
– 2、通常和static 关键字连用,让函数只在一个文件中使用,避免重定义。因为inline 函数通常是定义在头文件中的,不加static 关键字,如果没有内联成功的话,就会重定义。 - 注意:该关键字只有建议权,最终决定还是要看编译器。
如下图所示,连续调用
图片来自B站UP主宅学部落
attribute
起始地址和空间大小属性,可以设置函数(function attribute)、变量(variable attribute)、类型属性(type ~),。
- 作用,固定CPU变量间的相对位置。
- 示例,
图来自B站UP主米缸吃剩干燥剂
指针
地址,内容,指向变量3个方向理解,不管是几层指针。
妙用:
内存的应用划分
内存泄漏(memory leak)
- 定义:不正确的使用堆区域(申请之后未释放),导致内存一直在增长,最终超过限制而发生泄漏。
- 堆可以称为动态内存区域,不是固定的,可以按需生长。
图来自B站UPfengmuzi2003
随机数生成函数
rand();
函数返回值是指针
int* sum(int a, int b); // 需要保证返回值指针是指向堆区或者静态存储区的变量,不会释放。不能是指向栈里的。
int c = 0; // 定义静态存储区中的变量
int* sum(int a, int b)
{
c = a+b;
return &c;
}
// 或者使用堆
int* sum(int a, int b)
{
int* c= (int *)malloc(sizeof(int)); // 在堆上保证不会被自动释放。
*c = a+b;
return c
}
函数指针 和 回调函数
函数指针通常用于回调函数使用的场景,实现函数的调用。
“调用函数”和 “回调函数”配合使用,调用函数搭建函数框架和流程,回调函数实现具体功能。
举例:STM32中,定时器中断函数有多种触发情况,根据不同的触发情况实现不同的任务函数。在此就使用了回调函数。
常量指针
这个概念是面试是常遇到的问题,所以在此记录一下。
1) const char * myPtr = &char_A;//指向常量的指针
2) char * const myPtr = &char_A;//常量的指针
分析的原理:从右向左的优先级。
因此,第一个首先是指针,然后是常量。第二个首先是常量然后是指针。
指向常量的指针,被指向的内容是常量,所以不能修改。
// 指向常量的指针
char char_A = 'A';
const char * myPtr = &char_A;
*myPtr = 'J'; // error - can't change value of *myPtr
// 常量的指针
char char_A = 'A';
char char_B = 'B';
char * const myPtr = &char_A;
myPtr = &char_B; // error - can't change address of myPtr
实际差别:在于指针变量存放的地址能够修改,或者指向的变量的内容是否能够修改。
一般应用场景:传入的字符串不想被修改的场景中。
该部分内容参考链接:https://www.cnblogs.com/xwdreamer/archive/2012/04/12/2444494.html