前言:
标题有些长,是因为在实践中遇到的一个问题包含了多个知识点的综合应用,索性就一起说说。
目标代码如下:
typedef union{
unsigned int Byte;
struct
{
unsigned a : 1;
unsigned b : 1;
unsigned c : 1;
unsigned d : 1;
} Bits;
}tFault;
目标代码包含了typedef,union,struct及位域等标识符和知识点。
typedef和define
C 语言 typedef 与 #define 比较
typedef与define在功能上有部分重合,但二者也有显著不同,typedef是对数据类型的重定义,define是对字符串的简单替换,前者是编译阶段进行,后者是预处理阶段就执行了。
直接上代码:
typedef是对类型的重定义,且不可再加类型修饰
#define INTERGE int;
unsigned INTERGE n; //没问题
typedef int INTERGE;
unsigned INTERGE n; //错误,不能在 INTERGE 前面添加 unsigned
对于指针类型来说,可以理解为define只是简单的做了字符替换,而typedef相当于用括号把后面的包含了
#define PTR_INT int *
PTR_INT p1, p2; //p1、p2 类型不相同,宏展开后变为int *p1, p2;
typedef int * PTR_INT
PTR_INT p1, p2; //p1、p2 类型相同,它们都是指向 int 类型的指针。
typedef 由于是编译时执行,所以其有类型检查功能,并且typedef有作用域,而define没有.
void func1()
{
#define HW "HelloWorld";
}
void func2()
{
string str = HW;
cout << str << endl;
}
void func1()
{
typedef unsigned int UINT;
}
void func2()
{
UINT uValue = 5;//error C2065: 'UINT' : undeclared identifier
}
union联合体
又名共用体,字面意思,修饰的成员变量共用同一块内存,因此对其中某一成员的修改会覆盖其他成员的值。union在结构和用法上与struct基本一样,不同之处在于struct成员变量使用不同的内存,一块struct结构体的内存要略大于其成员变量内存总和。
union的理解如下:
初始时:
执行断点1后可见变量都发生了改变
最终运行结果:
4, 4
40, @, 40
39, 9, 39
2059, Y, 2059
3E25AD54, T, AD54
struct结构体
struct 修饰的语句为结构体成员,若做类比的话,结构体就如一张固定的图纸,结构体定义的变量就像图纸里的元件
同一个结构体定义的变量具有相同的特性
结构体具有字节对齐特性,以其包含的最长类型为模板对齐。比如一个结构体变量包含int ,char,long类型,则此结构体大小为12字节,
4+4(char本为1,被对齐为4)+4
struct结构体使用如下:
struct test
{
/* data */
int a;
char b;
};
struct test A;//C++不需要加struct
A.a=1;
struct
{
/* data */
int a;
char b;
}T,W;
T.a=1;W.b='c';//只能使用这两个结构体变量,不能再struct新结构体变量
特殊点的:
typedef struct tagNode
{
char *pItem;
struct tagNode *pNext;
} *pNode;
struct不允许用结构体定义成员变量,但允许定义指针,因为指针大小可以确认。
位域
位域详解
先看一个例子:
struct {
unsigned mode:8; //bit[0,7]:模式选择
unsigned en:1; //bit[8] :使能选择
unsigned reserved:1; //bit[9] :保留reserved (也可以写成unsigned reserved:1;)
unsigned clk_select:4; //bit[10,13]:时钟选择
unsigned ch_select:3; //bit[14,15]:通道选择
}reg11; //定义一个reg11变量,不声明结构体的好处在于确保变量唯一性
位域可单独操作某一寄存器数据位,比如对bit[8]赋值:reg11.en = 1;
位域越界:
当赋值:reg11.en=5; 时
系统会保留最低位,此时 en = 1;
当 reg11.en=6; 时 en = 0;