C语言----杂记

1、常量溢出

u16  adc_temp = 0;   //应为: u32  adc_temp = 0;
for(i=0;i<100;i++)
{adc_temp += usADC_CS1[i];  //usADC_CS1[i]数组里面每个元素大于1000,导致adc_temp溢出
}
adc_temp /= 100;

1.2、数据范围溢出

将一个数拆分为N个随机数

 for(i=0;i<200;i++)
{buffer[i] = Random(); //申请一个随机数val -= buffer[i];     //当申请得到的 buffer[i] > val; 结果将溢出if(val<0x100)         {if(val)           //排除 val = 0;{buffer[i+1] = val;}break;}
}

可更正为:

 for(i=0;i<200;i++)
{if(val>255) //大于0xff分解{buffer[i] = Random();val -= buffer[i];}else        //小于或等于0xff直接记录并退出{buffer[i] = val;break;}
}

 

2、头文件中宏定义与声明

#ifndef __bsp_11_H
#define __bsp_11_H		#include "stm32f10x.h"#define  Data_CodeLine       140
//u8 Data_CodeLine = 140;   //宏定义Data_CodeLine 为140是可以的,但是当//声明为u8类型的变量时,会报"多重定义"的错误#endif

原因是当此头文件被不同C文件“Include”时,两个C文件都分别声明Data_CodeLine,导致多重定义。

采用宏定义可以避免此问题。

3、数据的进制

		  STMFLASH_Write(0x8019000,FlashBuff,10);STMFLASH_Write(0x8019050,FlashBuff,10);for(i=0;i<2;i++)STMFLASH_Read(0x8019000+i*50,FlashBuff,10);  //应为i*0x50

 

原本第二次想读取0x8019050开始,连续10个半字大小的地址的数据。但是“i*50‘这里错误,应为”i*0x50“。否则将导致从0x8019032这个地址开始读取。

 

4、避免使用Null指针

举个例子,编译环境为visual studio 2015:

int main() 
{int *p1, Num = 1;*p1 = Num;printf("*p1 = %d",*p1);getchar();
}

咋一看没问题,其实会报错:

这是因为,声明的指针“p1”,没有指向任一内存地址。在编译器里它默认指向“Null”,所以从逻辑上来说,对“p1”指向的内存地址取值,这本身不可取。但如果是MDK编译,是不会报错的,可见VS的编译器还是比较强大的。

延伸一下,链表的创建问题。

      链表的创建,一般是先声明链表结构体的指针变量,再通过“malloc(); ”申请链表结构体大小的内存空间,并将空间起始地址赋值给这个指针变量。然后便能通过指针变量,操作它指向的内存空间的数据。这里通过“malloc(); ”申请内存赋值给指针变量的过程,就相当于给指针指定一个内存地址,这样它就不会是一个指向“Null”的空指针了。

      除了使用“malloc(); ”,还有别的办法使链表结构体指针变量指向某一地址,完成链表的创建吗。有的,方法如下:

#include 
#include //创建链表结构体
typedef struct Node
{int Data;struct Node *Next;
}Node;//声明链表结构体变量以及指针变量
Node  Head, Node1, Node2 ,Tail, *p4;int main() 
{//给链表结构体变量成员赋值Head.Data = 3;Head.Next = &Node1;Node1.Data = 11;Node1.Next = &Node2;Node2.Data = 22;Node2.Next = &Tail;Tail.Data = 0;Tail.Next = 0;//头结点地址赋值给链表结构体指针变量p4p4 = &Head;printf("p4->Data = %d\r\n",p4->Data);p4 = p4->Next;printf("p4->Data = %d\r\n", p4->Data);p4 = p4->Next;printf("p4->Data = %d\r\n", p4->Data);p4 = p4->Next;printf("p4->Data = %d\r\n", p4->Data);getchar();
}

编译运行结果为:


声明链表结构体变量的时候,变量的地址已经由系统分配完毕。

p4 = &Head;

当链表结构体指针变量指向头结点时,我们便能通过操作指针变量来操作头结点。

p4 = p4->Next;

当它改为指向指针域时,因为头结点指针域指向Node1,所以此时它指向Node1。

由“malloc(); ”申请内存创建的链表存储在动态存储区,使用灵活可删除。

而这种方法创建的链表存储在静态存储区,无法删除链表释放Ram。

5、char类型表示负数

在MDK下运行以下代码:

int main(void)
{volatile char  a1 = -1;volatile short a2 = 100;volatile int   a3 = 250;a3 -= a2*a1;while(1);
}

进入仿真,查看变量的值:

然后将“a1”的类型“char”改为“short”,问题解决。

后面找到问题了,是MDK编译器将“char”类型默认为“unsigned char”类型,可在MDK中修改:

6、指针作为数组的应用

uint8_t *pBuf;pBuf[0] = NRF24L01_RW(*pBuf++);
pBuf[1] = NRF24L01_RW(*pBuf++);
pBuf[2] = NRF24L01_RW(*pBuf++);
pBuf[3] = NRF24L01_RW(*pBuf++);
pBuf[4] = NRF24L01_RW(*pBuf++);	

 

原意是想,每发送一个数据,将发送缓冲数组中对应元素改为接收返回值。

但这里将指针当作数组使用出了问题。

分析  “pBuf[0] = NRF24L01_RW(*pBuf++);”

执行  1、“NRF24L01_RW(*pBuf);”

         2、“pBuf++;”

         3、 “pBuf[0]”等于 “NRF24L01_RW(*pBuf);”执行完毕的返回值

 

这里的问题是,“pBuf[0]”的地址是”pBuf“吗?

并不是的,因为第二步中,执行了“pBuf++;”,所以“pBuf[0]”的地址是”pBuf+1“

也就是说“pBuf[0]”变成了”“pBuf[1]“

 

7、"i++" 与 "++i" 的问题

int main() {int arr[] = { 3,4,5 }, *p1 = arr,y;y = *p1++ + (*(p1+++1)<<1);printf("%d\r\n",y);y = *p1;printf("%d\r\n", y);getchar();
}

以上程序输出结果:

11

5

第一个等式,“*(p1+++1)”,"++"优先级大于"+",先计算“(*p1+1)”,整个等式计算完毕后,p1再自增

由于第一个等式“p1”自增2次,所以第二个等式结果为5。

所以第一个等式等价于:y = arr[0] + (arr[1]<<1);

 

6、LKT4106加密芯片的坑

一个小小的加密芯片也能遇到很多坑。。。在这里慢慢填上

(1)

   u8  aa = 0x01, bb = 0xf4;u16 sum = 0;sum = ((aa<<8)|bb)/10;while(1){}

上述代码“sum”结果应该是“0x01f4”,但是LKT4106运行出来变成了0xf4。解决办法是分开一步步运行,不要写在一起。。。

(2)

   unsigned char aa = 0x11, bb = 0x22;unsigned long sum = 0;sum  = aa;sum |= bb<<8;while(1){}

理论上sum的值为“0x00002211”,实际上变成了“0xffff2211”.解决办法:

	 sum  = aa;sum |= (bb<<8)&0x0000ffff;

 


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部