1.将一个数值作为函数执行
(*(void(*)())0x13)();
同理也可以将数值换成一个变量:
int var=0x13;
(*(void(*)())var)();
具体原理解释参考:https://blog.csdn.net/qq_39117115/article/details/128299574
2.断言assert
用于判断输入的参数是否正确,实际就是判断输入的参数是否为0,如STM32的固件库中常用的assert_param(),当输入参数不为0(或NULL)的时候就是“(void)0",当输入参数为0的时候就会调用assert_failed(),assert_failed()函数可以自己定义,一般就是打印错误信息然后死循环卡死。
结构体位域
1.先说下结构体的定义:
结构体的定义只有一种形式,即:
如:
但是结构体变量的定义有4种形式,分别为:用结构体名定义结构体变量:
定义结构体的时候定义结构体变量:
省略结构体名直接定义结构体变量:
用某一结构体类型,定义结构体变量:
typedef struct
{
char *name;
int age;
int height;
}student_type;
student_type stu;
OK,言归正传,说说结构体位域:
位域的基本形式就是:
struct test_st
{char a:5;char b:2;char c:2;char d:4;
}tc;
冒号后面的数字就是表示其占了该字节的几个位,如a占了5个位,其取值范围就是2^5次方,b就是2的2次方;
需要注意的是:
1.位域不能跨字节,如位域c并不是占了第一字节的最后一个位(最高位),然后占了第二字节的第一个位,而是直接从第二字节开始的;
2.由于上述特性,所以位域的长度(位数)不能大于8
3.位域可以无位域名,这种情况可以用来作填充或调整位置,如:
struct test_st
{char a:5;char b:2;char :1;char c:2;char d:4;
}tc;
4.如果位域的长度为0,表示是个空域,同时下一个位域会从下一个字节开始存放。
5.位域的一个作用是缩减程序大小,如上诉位域,5个char型变量实际只占用2个字节;但是如果位域的类型为int型的话,就得加上个一字节对齐的编译器指令了(#pragma pack(1)),否则将会占用4个字节;
6.位域是从一个字节的低位开始存储的,如a存储在第一个字节的0-4位上,b存在5-6位上。