1. 当流水线充满指令时,即每个时钟周期执行一条指令(仅限单周期指令)时,可以实现最大性能。 如果发生程序跳转,流水线就会被清空,需要几个时钟周期才能再次填满流水线。 因此,尽量少使用跳转指令可以提高程序执行效率。 解决办法就是尽可能使用指令的“条件执行”功能。
2. 系列中:
您可以通过以下步骤延迟 10 毫秒:
3. 通过以下语句将一个 16 位变量放入两个 8 位变量中。
//IP数据报总长度高字节
[10]=(.e_ip.Crc&)>>8;
//IP数据报总长度低字节
[11]=.e_ip.Crc&;
4、给所有数组元素赋初始值时,不需要指定数组长度。
例如;inta={1,2,3,4,5};
但是,如果输出a[5]上面的元素,系统将输出一个随机值。 因此,使用该方法时,不能使用超过初始值元素的元素。
5、由于ADS不支持先天配对,所以不方便我们调试。 我们可以使用串口输出来代替调试。
6. 使用OR 运算,可以将某个位设置为1,而其他位保持不变。
例如:|=; //设置串口引脚
将第 0 位和第二位设置为 1,其他位保持不变。
7. 函数指针
1> C语言中的函数名直接对应于该函数生成的指令代码在内存中的地址,因此可以将函数名直接赋值给指向该函数的指针。
2> 调用函数实际上相当于“调用指令+参数传递处理+返回位置到堆栈”。 本质上,核心操作就是将函数生成的目标代码的首地址赋值给CPU的PC寄存器。
3> 因为函数调用的本质是跳转到某个地址单元的代码处执行,所以有可能“调用一个根本不存在的函数实体”。
4> int(*p); 将p定义为指向函数的指针变量,函数返回一个整数返回值。 *P两边的括号不能省略,说明p先和*结合起来,是一个指针变量,再和后面的结合起来,说明这个指针指向一个函数。
区别:int *p表示该函数的返回值是一个指向整型变量的指针。
阐明:
(1) 指向函数的指针变量的一般定义形式为:
数据类型(*指针变量名);
1> 这里的“数据类型”是指函数返回值的类型
(2) 返回指针值的函数:
类型名*函数名(参数列表)
例如: int * func(int x,int y)
func 是函数的名称。 调用它后,它可以返回一个指向整数数据的指针。 x, y 是 func 的形式参数。
差异法:
A。 从右到左找到第一个括号。 括号里面的是函数的形参。
b. 括号外的第一个标识符是函数的名称,函数前面的表示函数的返回值。
8. 数组指针
1>int (*p)[4]
表示*p有4个元素,每个元素都是一个整数。 即p指向的对象有一个由4个整型元素组成的数组,即P是行指针。
2> 指针数组
Ø 元素均为指针类型数据的数组称为指针数组; 也就是说,指针数组中的每个元素相当于一个指针变量。
Ø 一维指针数组的定义形式为:
类型名*数组名[数组长度]
例如:int *p[4]:
作用:用于指向多个字符串,使字符串处理更加方便灵活。适用于每行字符数组长度不同的二维字符串数组
例如:char * name={"me","BASIC",""};
9. 结构
1> 可以使用结构体变量作为实际参数。 但当结构体变量作为实参时,则采用“传值”方式,将结构体变量占用的内存单元的内容全部依次传递给形参。 形式参数也必须是相同类型的结构变量。
eg:pint(su);//注意这里su是一个结构体
注意:这种传输方法在空间和时间上都很昂贵。 如果结构体规模很大,开销就相当可观。
2> 使用指向直结构变量(或数组)的指针作为实参,并将结构变量(或数组)的地址传递给形参
eg:print(&su);//注意这里su是一个结构体
10. 社区
1> 联合体将几种不同数据类型的变量存储在同一个内存中。 共同体中的变量共享相同的内存。
2> 定义公共类型变量的一般形式为:
工会 工会名称
会员名单;
}变量列表;
3>联合体中的同一块内存可以用来存储几种不同类型的数据,但在某一时刻只能存储一个成员变量。 联合变量的有效成员是最后存储的数据。
联合变量a中的三个变量i、c、d在内存中从同一地址开始存储。 例如,进行以下分配:
艾 = 100;
交流=“A”;
那么此时联合变量a中的成员i已经没有值了,因为存储该值的内存现在已经用来存储成员c的值了。
3> 联合变量的长度取决于其成员的最大长度:
阐明:
结构体变量占用的内存长度是其成员的总和,每个成员占用自己的存储空间。 联合变量占用的内存长度是其最长成员的长度。 当然,为了提高访问效率,编译器在编译和分配存储空间时,常常会进行对齐操作。
对齐操作基于最大的基本类型。 即以最大的基本类型作为基本单位。 如果实际计算长度不是基本单位的整数倍,则实际长度应为基本单位的整数倍。
(Linux下不对齐,Linux下对齐)
11、处理CPU字长和内存位宽不一致的问题
例如:使用 union 来解决这个冲突:
联盟{
字;
uint8 字节[2];
};
eg:.bytes[0]=a;//这里a是8位
.bytes[1]=b;//这里b是8位;
此时,8位字被拼成16位字并存储。
发送时,send(.words)每次可以发送16位数据。
12.C语言符号优先级:
1>复合赋值运算符符号:
a+=3*5;
相当于a=a+(3*5);
13. 一种常见的调试策略是在整个程序中分散一些函数调用,以确定发生错误的具体位置。 然而,这些函数调用的输出被写入缓冲区,并且不会立即显示在屏幕上。 事实上,如果程序失败,缓冲的输出可能实际上没有被写入,因此获得的错误位置将是错误的。 解决方案是在每个用于调试的函数之后立即调用该函数。
14. 关键词的使用
变量可以在以下情况下使用:
1>设备的硬件寄存器(如:状态寄存器)
2>将在中断服务子程序中访问的全局变量
3>多线程应用程序中多个任务共享的变量。
15.关键词的使用:
当一个变量被频繁读写时,需要重复访问内存,这会占用大量的访问时间。 为此,C语言提供了一种变量,即寄存器变量。 这种变量存储在CPU的寄存器中。 使用时不需要访问内存,而是可以直接从寄存器中进行读写,从而提高效率。 寄存器变量的说明符是。 循环次数较多的循环控制变量以及循环体中重复使用的变量都可以定义为寄存器变量,而循环计数是应用寄存器变量的最佳选择。
(1) 只有局部自动变量和形式参数才能定义为寄存器变量。 由于寄存器变量是动态存储方式,任何需要静态存储方式的量都不能定义为寄存器变量,包括:模块间全局变量、模块内全局变量、局部变量;
(2)是“”关键字,意思是程序建议将该变量放在寄存器中,但最终该变量可能因为不满足条件而不会成为寄存器变量,而是放在内存中,但是编译器没有报错(C++语言中还有一个“”关键字:)。
16.对于已经烧录在FLASH或ROM中的程序代码,我们可以让CPU直接从中读取代码并执行,但通常这不是一个好办法。 最好在系统启动后将目标转移到FLASH或ROM中。 代码被复制到RAM中然后执行以提高取指令速度。
CPU对各种存储器的访问速度基本上是:
CPU 内部 RAM > 外部同步 RAM > 外部异步 RAM > FLASH/ROM
17. 宏定义
在C语言中,宏是生成内联代码的唯一方法。 对于嵌入式系统来说,宏是替换函数以满足性能要求的好方法。
1>宏定义“like”函数;
2>宏定义不是函数,所以需要将所有“参数”括起来;
3>宏定义可能有副作用。 因此,不要传入对宏定义有副作用的“参数”。
【教程资料】:如果您对以下信息感兴趣,可以阅读; 学习技术组:
C语言编程基础
强化C语言,从新手进阶到专家!
指针
您还记得指针的变化吗?
C语言控制led灯
C语言实现面向对象编程
数据结构栈
数据结构排序题目