二、__attribute__、结构体指定成员所占内存长度做法、强制转换类型的使用、sscanf函数——解析并转换字符串

本文介绍了C语言中attribute关键字用于指定变量的内存位置,如固化的信息存储在flash或大缓存数据存储在RAM。结构体的位段特性允许以位为单位节省内存。强制转换类型在指针操作中的应用,以及sscanf函数解析和转换字符串的基本及高级用法,包括整数、浮点数和混合数据类型的提取。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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;

其所占的内存长度示意如右img

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值