1。只有当流水线被指令填满时,即每个时钟周期完成一条指令的执行(仅指单周期指令),才能达到最大性能。如果程序跳转,管道被清空,管道再次填满需要几个时钟。因此,尽可能少地使用跳转指令可以提高程序执行的效率,解决的办法就是尽可能地使用指令的“条件执行”功能。2、在LPC2200系列中:可以通过如下程序延时10毫秒:for(i=0;i<200;i++){for(j=0;j<200;j++);}3、使用如下语句to一个16位变量放在两个8位变量中。//IP数据报总长度高字节IpHeadUint8[10]=(IpHead.e_ip.Crc&0xff00)>>8;//IP数据报总长度低字节IpHeadUint8[11]=IpHead.e_ip.Crc&0x00ff;4.给所有数组元素赋初值时,可以不指定数组长度。例如;inta={1,2,3,4,5};但是如果在输出a[5]以上的元素时,系统会输出随机值,所以在使用该方法时,不能使用超过初始值的元素元素。5、因为ADS本身不支持printf;不方便我们调试。我们可以用串口输出代替printf来调试。6.用OR运算使某位为1,其他位不变eg:PINSEL0|=0x00000005;//设置串口引脚使第0位和第2位为1,其他位不变。7.函数指针1>C语言中的函数名直接对应函数生成的指令代码在内存中的地址,因此函数名可以直接赋值给指向函数的指针。2>调用一个函数其实就相当于“调用指令+参数传递处理+返回栈位”。核心操作是将函数生成的目标代码的首地址赋值给CPU的PC寄存器。3>因为函数调用的本质是跳转到某个地址单元的代码去执行,所以可以“调用一个根本不存在的函数实体。4>int(*p);定义p为一个指向函数的指针变量,次函数返回一个整型返回值*P两边的括号不能省略,说明p在它是指针变量之前先和*结合,再和后者结合,说明this指针指向一个函数区别:int*p表示这个函数的返回值是一个指向整型变量的指针。说明:(1)指向函数的指针变量的一般定义形式为:数据类型(*指针变量名);1>这里的“数据类型”指的是函数返回值的类型(2)返回指针值的函数:类型名*函数名(参数表)eg:int*func(intx,inty)func是函数名,调用后可以返回一个指向整型数据的指针。x,y是func的形参。如何区分:A.从右到左找到第一个括号,括号内是函数的形参。b.括号外的第一个标识符是函数名,函数前面的表示函数的返回值。8、数组指针1>int(*p)[4]表示*p有4个元素,每个元素都是整数。即p指向的对象有一个4个整数元素的数组,即P是一个行指针。2>指针数组?元素全部为指针类型数据的数组,称为指针数组;也就是说,指针数组中的每个元素都相当于一个指针变量。?一维指针数组的定义形式为:类型名*数组名[数组长度]例:int*p[4]:功能:用于指向多个字符串,使字符串处理更加方便灵活。适用于二维字符串数组,每行字符数组长度不同eg:char*name={“Followme”,”BASIC”,”GreatWall”};9.结构体1>可以使用结构体变量作为实参。但在使用结构变量作为实参时,采用“传值”的方式,将结构变量所占内存单元的所有内容依次传递给形参。形式参数也必须是相同类型的结构变量。eg:pint(su);//注意这里su是一个结构体。注意:这种传输方式在空间和时间上都有较大的开销。如果结构的规模很大,开销是相当可观的。2>使用指向结构体变量(或数组)的指针作为实参,将结构体变量(或数组)的地址传递给形参eg:print(&su);//注意这里的su是结构体10.Union1>union将几种不同数据类型的变量存储在同一块内存中。公共主体中的变量共享相同的内存。2>定义普通类型变量的一般形式为:unionunionname{memberlist;}variablelist;3>union中的同一块内存可以用来存放几种不同类型的数据,但是在某个时刻里面只能存放一个成员变量。联合变量的活跃成员是最后存储的数据。例如:uniondata{inti;charc;doubled;};uniondataa;联合变量a中的成员i、c、d都是从内存中的同一个地址存放的。例如,下面的赋值:a.i=100;a.c='A';那么此时联合变量a中的成员i就没有值了,因为存放这个值的内存现在被用来存放成员c的值了。3>联合变量的长度取决于其成员的最大长度:注:结构变量占用的内存长度是每个成员的总和,每个成员占用自己的存储空间。联合变量占用的内存长度是其最长成员的长度。当然,为了提高访问效率,编译器在编译和分配存储空间时,往往会进行对齐操作。对齐操作基于最大的原始类型。即以最大的基本类型作为基本单位。如果实际计算的长度不是基本单位的整数倍,则其实际长度应为基本单位的整数倍。(TurboC不做对齐,Linux做对齐)11、CPU字长和内存位宽不一致。例如:使用union解决这个冲突:unionsend_temp{uint16words;uint8bytes[2];}send_buff;eg:send_buff.bytes[0]=a;//这里a是8位send_buff.bytes[1]=b;//这里b是8位;此时,8位字被拼成16位字存储。发送时,send(send_buff.words)每次可以发送一个16位的数据。12、C语言符号优先级:1>复合赋值运算符:a+=3*5;相当于a=a+(3*5);13.一种常见的调试策略是在程序中分散一些printf函数调用,以确定错误的确切位置。但是,这些函数调用的输出会写入缓冲区,不会立即显示在屏幕上。事实上,如果程序失败,缓冲的输入可能并没有真正被写入,因此导致的错误位置将是错误的。解决方法是在每个printf函数后立即调用fflush函数进行调试。printf("somethingorother");fflush(标准输出);14.关键字volatile的用法volatile变量可能用在以下几种情况:1>设备的硬件寄存器(如:状态寄存器)2>一个中断服务子程序会访问到全局变量3>几个共享的变量多线程应用程序中的任务。15.关键字register的用法:当一个变量被频繁读写时,需要反复访问内存,从而花费大量的访问时间。为此,C语言提供了一种变量,即寄存器变量。这种变量存储在CPU的寄存器中。使用时不需要访问内存,直接从寄存器读写,提高效率。寄存器变量的说明符是register。循环次数较多的循环控制变量和循环中重复使用的变量都可以定义为寄存器变量,而循环计数是寄存器变量的最佳候选。(1)只有局部自动变量和形参可以定义为寄存器变量。由于寄存器变量属于动态存储方式,任何需要静态存储的量都不能定义为寄存器变量,包括:模块间全局变量、模块内全局变量、局部静态变量;(2)registerisa"recommended"key这个词的意思是程序建议将变量放在寄存器中,但最终变量可能因为不满足条件而没有成为寄存器变量,而是放在内存,但编译器不报错(在C++语言中,还有另一个“建议”类型关键字:inline)。16、对于已经烧录在FLASH或者ROM中的程序代码,我们可以让CPU直接从里面读取代码执行,但是通常这不是一个好办法,我们最好把target放在FLASH或者ROM中系统启动后将代码复制到RAM中执行,以提高取指令速度。CPU对各种存储器的访问速度基本上是:CPU内部RAM>外部同步RAM>外部异步RAM>FLASH/ROM17。宏定义在C语言中,宏是生成嵌入式代码的唯一途径。对于嵌入式系统,为了满足性能要求,宏是函数的一个很好的替代方案。1>宏定义“像”一个函数;2>宏定义不是函数,所以需要把所有“参数”都括起来;3>宏定义可能会产生副作用。所以不要传入对宏定义有副作用的“参数”。
