1、attribute( at(绝对地址) )的使用
这个关键字的的意思是指定变量的地址,如uint8_t testValue attribute(at(0x20005000));表示指定变量testVale的地址为0x20005000
这个关键字的作用主要有如下两个:
(1)定位到flash中,一般用于固化的信息,如出厂设置的参数,上位机配置的参数,ID卡的ID号,flash标记等等
(2)定位到RAM中,一般用于数据量比较大的缓存,如串口的接收缓存,再就是某个位置的特定变量。
在使用的过程中需要注意下面两点:
(1)绝对定位不能在函数中定义,局部变量是定义在栈区的,栈区由MDK自动分配、释放,不能定义为绝对地址,只能放在函数外定义。
(2)定义的长度不能超过栈或Flash的大小,否则,造成栈、Flash溢出。
2、结构体指定成员所占内存长度做法
C语言允许在一个结构体中以位为单位来指定其成员所占内存长度,这种以位为单位的成员称为“位段”或称“位域”( bit field) 。利用位段能够用较少的位数存储数据。
即如果定义了如下结构体
struct
{
unsigned a:2;
unsigned b:6;
unsigned c:4;
unsigned d:4
int i;
}data;
其所占的内存长度示意如右
3、强制转换类型的使用
(1)强制转换为指针
int16_t Anto[12];
int8_t *pt = (int8_t*)(Anto);
经上面的强制转换复制之后Anto[0] 的数据存放占16位,其低八位存放到 (pt+0)内存地址里面;高八位存放在(pt+1)内存地址里面。
即如果执行如下代码
#include <stdio.h>
typedef signed char int8_t;
typedef signed short int int16_t;
typedef signed int int32_t;
int main()
{
int16_t Anto[12];
int8_t *pt = (int8_t*)(Anto);
Anto[0]=258; //使用16bit表示为 0000 0001 0000 0010
printf("%d\r\n",Anto[0]);
printf("%d\r\n",*(pt)); //低8位先放进去即 0000 0010 十进制表示为2
printf("%d\r\n",*(pt+1));//这里存放点俄是高8位数据0000 0001 十进制为1
return 0;
}
其运行结果为
4、sscanf函数——解析并转换字符串
(1)基本用法
整数:
int year, month, day;
int converted = sscanf("20191103", "%04d%02d%02d", &year, &month, &day);
printf("converted=%d, year=%d, month=%d, day=%d/n", converted, year, month, day);
其输出结果将为:
converted=3, year=2019, month=11, day=03
具体解释如下:
1)"%04d%02d%02d"是用来解析字符串的格式,%表示格式转换的开始,d表示转换为一个整数,04作为d的修饰,表示这是一个长度为4位的整数,不足4位时以0补齐。
2)该参数的返回值为转换成功数目
浮点数:
double longitude, latitude;
int converted = sscanf("113.123456789 31.123456789", "%lf %lf", &longitude, &latitude);
printf("converted=%d, longitude=%.9lf, latitude=%lf/n", converted, longitude, latitude);
//其运行结果如下,修饰词l表示这是一个double的浮点数。
converted=2, longitude=113.123456789, latitude=31.123457
(2)高级用法
数字加字符串:
char str[32] = "";
sscanf("123456abcdedf", "%31[0-9]", str);
printf("str=%s/n", str);
其输出结果为:
str=123456
具体解释如下:
1)[0-9]表示这是一个仅包含0-9这几个字符的字符串。
2)前面使用数字31修饰词表示这个字符串缓冲区的最大长度
所以变形用法有以下三种:
//第一种
char str[32] = "";
sscanf("123456abcdedf", "%31[0-9a-z]", str);
printf("str=%s/n", str);
//输出结果如下,在格式[]中增加了a-z的描述
str=123456abcdedf
//第二种
char str[32] = "";
sscanf("123456abcdedf", "%31[^a-z]", str);
printf("str=%s/n", str);
//输出结果如下,在[]中增加表示相反的意思,上面的[a-z]表示一个不包含任何a-z之间的字符串。
str=123456
//第三种
char str[32] = "";
int ret = sscanf("123456abcdedf", "%*[0-9]%31[a-z]", str);
printf("ret=%d, str=%s/n",ret, str);
//输出结果如下,加上*修饰表示一个被忽略的数据,同时也不需要为它准备空间存放解析结果。
ret=1, str=abcdedf