😃韦东山C语言加强课,截图+代码+学习笔记【2000字】【原创】
😀韦东山FreeRtos的内部机制,截图+学习笔记【2000字】【原创】
😃韦东山C语言加强课,截图+代码+学习笔记【2000字】【原创】
😀韦东山FreeRtos的内部机制,截图+学习笔记【2000字】【原创】
韦东山C语言加强
.map文件中data中存放的是初始化的全局变量(局部变量放在栈里面),flash保存程序代码,RAM内存保存数据
指针存放的是地址=0xXXXXXXXX,32位机器地址是4个字节,不同位数机器的指针字节数不定,我的电脑就是32位=4个字节
char a = ’A’;
char *p = &a;
此时a就是一个字节,而p就是四个字节
上面的提问是正确的
volatile关键字就是,防止被编译器优化,i=1;这条语句可以省略优化,但是加上这个关键字,
就不会被省略优化了,有些情况下,cpu将数据备份在cpu里面(这样速度会变快),而不是从ram里面读取了,会引起某些误操作,
这个static定义的变量wei,说明这个变量只起作用在main.c文件里面。假如main里面定义一个变量wei,而另一个serial文件下面也定义了这个变量wei,main里面加上static代表,main里面使用的这个变量wei和serical表示两个变量不冲突了,serical的wei不在main里面起作用其他文件都起作用,main的wei只在main里面起作用,不在其他文件起作用
extern只是声明语句,这里当做赋值语句肯定不对
类型不是变量,不占空间,只有赋值,实例化才分配空间
用奇数地址来访问int4个字节地址效率很低,甚至有些系统不支持
想要看到d被破坏成0的结果,可是没有看到,弹幕提示可能地址不连续
理论上d会被破坏成0
放在了结构体中,试验成功了
20230130注:是因为指针=地址占用四个字节,因此挤兑了d的位置,将d的数值清成了0
flash可以理解为代码
只要是指针,它就是存放地址,无论是int*类型还是结构体类型,都是四个字节,也就是说,pt和p都是占用四个字节
20230130注:p的地址是否等于pt的地址,也就是说a的地址和c的地址谁是0x2000 0004?
黑色×不是错误的意思,是不建议这样使用
不建议使用全局变量int b,良好的编程习惯是加上static,使得b只在b.c文件下面范围,如果是int b
不能这样无线套娃,鹏哥C语言也说了不可以,这个和递归也不一样
这样是可以的,定义了一个结构体和一个结构体指针
这样不严谨,不知道你定义的函数返回值是指针呢(红色),还是定义了一个函数指针呢(蓝色)
这里是定义了一个变量,play_ball2是一个变量,相当于int *p中的p,只要是变量,就一定会有存储空间,只要是地址,甭管什么类型,一定是4个字节空间
这个for循环里面,如果有多个成员,那么一个个写很麻烦
带上指针之后,甭管多少成员,都只需要这一行代码即可
同样的,为了避免写多个if判断,我们就可以想到用到结构体指针,来简化操作
此时定义了一个结构体和一个结构体指针,其中结构体成员有一个函数指针
这下就省去了if的判断语句①
返回地址而不是返回结构体,是因为结构体空间要大,指针只有四个字节,速度要快些 ②,上面两个功能是一样的
类比法,第一个int=A,第二个int*=B,第五个函数指针类型=int (*add)(int, int)相当于int *
int (add_type)(int, int)=add_type,前者是函数指针类型,add_type f1;简化了语句,f1是指向函数的指针,内容是地址
p_spy是结构体指针,指针就是固定四个字节,①看着不是很习惯,看久了就好了,不习惯是因为看不到号
这个while循环就可以遍历出所有的成员了,即打印出ABC,首先要创建一个空指针,这是所有的第一步=NULL
#include <stdio.h>
//struct spy//以下注释都是我写的错误代码
//{
// char name;
// struct spy *next;
//}spy1;
//
//struct spy
//{
// char name;
// struct spy* next;
//}spy2;
//
//struct spy
//{
// char name;
// struct spy* next;
//}spy3;
//
//int main()
//{
// struct spy1 = {'A',NULL};
// struct spy2 = { 'B',NULL };
// struct spy3 = { 'C',NULL };
//
// struct spy* head = NULL;
// head = &spy1;
// while (1)
// {
//
// }
//
// return 0;
//}
typedef struct spy
{
char name;
struct spy* next;
}spy, *p_spy;
spy A = { 'A', NULL };
spy B = { 'B', NULL };
spy C = { 'C', NULL };
spy D = { 'D', NULL };
p_spy head = NULL;
void insert_spy(p_spy newspy)
{
p_spy last = NULL;
if (NULL == head)//说明此时头部没有指向,因为这个插入就是第一个
{
head = newspy;
newspy->next = NULL;//尾巴为空
}
else
{
last = head;//头部不为空,说明不是第一个了
while (last->next)//跳出说明遇到了最后一个
{
last = last->next;
}
last->next = newspy;//此时插在上面跳出的那个后面
newspy->next = NULL;
}
}
int main()
{
//p_spy* head = NULL;//一开始写成这样了,肯定不对
//while (1);//这个while循环代码不报错,但是运行报错
//{
// head = &A;
// printf("%c\r\n",head->name);
//}
//A.next = &B;
//B.next = &C;
//C.next = &D;
//D.next = NULL;
insert_spy(&A);//用这四行代替上面四行结果一样
insert_spy(&B);
insert_spy(&C);
insert_spy(&D);
head = &A;
//while (1);//这行代码也是不报错,运行报错
//{
// printf("%c\r\n", head->name);
// head = head->next;
//}
while (head)//我靠,原来是while()后面加了个;号,所以才出错,淦
{
printf("%c\r\n", head->name);
head = head->next;
}
return 0;
}
以上是链表的知识,我把代码写在了vs2019里面,链表的插入还是没有怎么明白,太难了
hex文件也烧在flash里面,数据段在flash里面,上电时,flash里面的数据转移到rom里面,为了提高效率,flash才会以段的形式存在,一整块一整块向rom转移,从flash读取数据,将数据存在变量在rom地址里面,
假如有一百万个全局变量,数据段都放在一起,对于向rom整体转移很方便,提高效率,
这些一百万个未初始化或者为0的全局变量,放在flash里面很浪费空间,因此我们直接放在rom里面即可,因为它的数据我们已经知道是0了,使用一个函数直接在rom里面清零即可,是吧很方便,放在zi段
栈=一块内存,它可以保存很多东西,LR寄存器是保存地址的寄存器,为了防止LR寄存器被覆盖,导致之前保存的地址丢失,所以将地址暂时保存在栈里面
lr,r4-r2都是寄存器,r3保存a,r2保存b,局部变量只能一个一个来,不像全局变量那样整块存取,完结撒花。