常用数据转换, 常用内存相关函数, 常用关键字

1. 数组转16进制字符

static const char *hexdigits = "0123456789ABCDEF";	
void data2hex(const void *data, uint32_t len, char *str)
{	
	const uint8_t *cdata = (uint8_t *data);
	for (uint32_t i=0; i<len; i++) {
		str[i*2	 ] = hexdigits[(cdata[i] >> 4) & 0xF];
		str[i*2+1] = hexdigits[cdata[i] & 0xF];
	}
	str[len*2] = 0;
}

2. 整数转16进制字符

static const char *hexdigits = "0123456789ABCDEF";
void uint32hex(uint32_t num, char *str)
{
	for (uint32_t i=0; i<8; i++) {
		str[i] = hexdigits[(num >> (28 - i*4)) & 0xF];
	}
}

3. 内存数据存放结构化

/* 存放数据起始地址  */
#define FLASH_STORAGE	(0x08000000)

/* 将地址转化为字节类型, 用于按字节访问  */
#define FLASH_PTR(x)	(const uint8_t *)(x)

/* 宏定义数据结构指针, 指向结构首地址 */
#define storageRom	( (const Storage *)FLASH_PTR(FLASH_STORAGE) )

/* 宏定义各种简单/复合结构的数据类型 */
#define STORAGE_BOOL(NAME)		STORAGE_FIELD(bool,          NAME)	
#define STORAGE_NODE(NAME)		STORAGE_FIELD(StorageHDNode, NAME)
#define STORAGE_UINT32(NAME) 	STORAGE_FIELD(uint32_t,      NAME)

/* 数据结构中的复合类型的数据结构定义 */	
#define STORAGE_FIELD(TYPE, NAME)	\
	bool	has_##NAME;				\
	TYPE	NAME;

/* 数据结构中的指定长度的字符串结构 */	
#define STORAGE_STRING(NAME, SIZE)	\
	bool 	has_##NAME;				\
	char 	NAME[SIZE];
	
/* 数据结构中的指定长度的数组结构定义 */	
#define STORAGE_BYTES(NAME, SIZE)	\
	bool	has_##NAME;				\
	struct	{						\
		uint32_t	size;			\
		uint8_t		bytes[SIZE];	\
	}NAME;
Note: has_##NAME 用于表示该字段数据是否有效
	
/* 内存中存放的数据结构定义 */
typedef struct {
	uint32_t	depth;
	uint32_t 	fingerprint;
	uint32_t	child_num;
	struct {
		uint32_t	size;
		uint8_t		bytes[32];
	}chain_code;
	
	STORAGE_BYTES(private_key, 32);
	STORAGE_BYTES(public_key, 33);
}StorageHDNode;

/* 内存中存放的数据结构 */
typedef struct _Storage {
	uint32_t	version;
	STORAGE_NODE	(node)
	STORAGE_STRING	(mnemonic, 241)
	STORAGE_BOOL	(passphrase_protection)
	STORAGE_UINT32	(pin_failed_attempts)
	STORAGE_BYTES	(homescreen, 1024)
}Storage; 

4. 结构内部访问接口

typedef uint32_t size_t;
/* 返回结构体成员变量在结构中的偏移位置, 4字节对齐 */
#define offsetof(st, m)	((size_t)( &((st *)0)->m) )

/* 计算成员变量的大小 */
#define membersize(st, m)	(sizeof((st *)0)->m)

/* 获取数据结构所占的内存大小, 4字节对齐 */
#define STORAGE_SIZE(last_member) 	( ((offsetof(Storage, last_member) + membersize(Storage, last_member)) + 3) & ~3)

e.g:
	size_t storage_size = 0; 
	storage_size = OLD_STORAGE_SIZE(homescreen);
	
	if (storage_size  != sizeof(Storage)) {
		/* 数据结构已添加新成员, 处理函数1 */
	}
	else {
		/* 数据结构没变, 处理函数2 */
	}
Note: 常用于兼容旧版本消息结构, 新成员只能在最后添加

5. 常用函数实现

/* 获取字符串的字节数, 不计算结束符'\0'nst */
static size_t strlen(const char * s)
{
	size_t rc = 0;
	while (s[rc]) {
		++rc;
	}
	return rc;
}

/* 拷贝指定长度的数据 */
static void * memcpy(void *s1, const void *s2, size_t n)
{
	char *dest = (char *)s1;
	const char *src = (const char *)s2;
	while (n--) {
		*dest++ = *src++;
	}
	return s1;
}

/* 将指定长度地址数据初始化为指定值 */
static void * memset(void *s, int c, size_t n)
{
	unsigned char *p = (unsigned char *)s;
	while (n--) {
		*p++ = (unsigned char)c;
	}
	return s;
}

6. 关键字用法

  1. const
    优点:
    1. 定义 const 常量, 具有不可变性.
    2. 便于进行类型检查, 消除隐患.
    3. 保护被修饰的东西, 防止意外的修改, 增强程序的健壮性.
    4. 为函数重载提供参考.
    5. 节省空间, 避免不必要的内存分配.
    e.g:
    #define PI 3.14159 //常量宏
    const double Pi = 3.14159; //const 修饰常量, 此时未将 Pi 放入 ROM 中
    double I = PI; //预编译期间宏替换, 分配内存
    double i = Pi; //此时为Pi 分配内存, 以后不再分配
    double J = PI; //再进行宏替换, 又一次分配空间
    double j = Pi; //没有内存分配

  2. 修饰常量
    int const x = 0;
    const int x = 0;

  3. 修饰常数组
    int const a[3] = {1, 2, 3};
    const int a[3] = {1, 2, 3};

  4. 修饰常指针
    const int *p; //const 修饰指向的对象, p 可变, p 指向的对象不可变
    int const *p; //同上
    int *const p; //const 修饰指针 p, p 不可变, p 指向的对象可变
    const int *const p; //指针 p 和 p 指向的对象均不可变

  5. 修饰常引用
    const double &var; //该引用所引用的对象不能被更新

  6. 修饰函数常参数
    void func(const int var); //告诉编译器 var 在函数体中无法改变, 防止使用者的一些无意或错误的修改

  7. 修饰函数的返回值
    const int func(); //表示函数返回值不可被改变

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值