1、常量溢出
u16 adc_temp = 0; //应为: u32 adc_temp = 0;
for(i=0;i<100;i++)
{
adc_temp += usADC_CS1
; //usADC_CS1数组里面每个元素大于1000,导致adc_temp溢出
}
adc_temp /= 100;
1.2、数据范围溢出
将一个数拆分为N个随机数
for(i=0;i<200;i++)
{
buffer = Random(); //申请一个随机数
val -= buffer; //当申请得到的 buffer > val; 结果将溢出
if(val<0x100)
{
if(val) //排除 val = 0;
{
buffer[i+1] = val;
}
break;
}
}
可更正为:
for(i=0;i<200;i++)
{
if(val>255) //大于0xff分解
{
buffer = Random();
val -= buffer;
}
else //小于或等于0xff直接记录并退出
{
buffer = 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;
//头结点地址赋值给链表结构体指针变量p4
p4 = &Head;
printf("p4->Data = %drn",p4->Data);
p4 = p4->Next;
printf("p4->Data = %drn", p4->Data);
p4 = p4->Next;
printf("p4->Data = %drn", p4->Data);
p4 = p4->Next;
printf("p4->Data = %drn", 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("%drn",y);
y = *p1;
printf("%drn", 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;
1、常量溢出
u16 adc_temp = 0; //应为: u32 adc_temp = 0;
for(i=0;i<100;i++)
{
adc_temp += usADC_CS1
; //usADC_CS1数组里面每个元素大于1000,导致adc_temp溢出
}
adc_temp /= 100;
1.2、数据范围溢出
将一个数拆分为N个随机数
for(i=0;i<200;i++)
{
buffer = Random(); //申请一个随机数
val -= buffer; //当申请得到的 buffer > val; 结果将溢出
if(val<0x100)
{
if(val) //排除 val = 0;
{
buffer[i+1] = val;
}
break;
}
}
可更正为:
for(i=0;i<200;i++)
{
if(val>255) //大于0xff分解
{
buffer = Random();
val -= buffer;
}
else //小于或等于0xff直接记录并退出
{
buffer = 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;
//头结点地址赋值给链表结构体指针变量p4
p4 = &Head;
printf("p4->Data = %drn",p4->Data);
p4 = p4->Next;
printf("p4->Data = %drn", p4->Data);
p4 = p4->Next;
printf("p4->Data = %drn", p4->Data);
p4 = p4->Next;
printf("p4->Data = %drn", 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("%drn",y);
y = *p1;
printf("%drn", 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;
举报