条件编译
编译器根据条件的真假决定是否编译相关的代码**(非常常用)**
常见的条件编译有两种方法:
- 根据宏是否定义,其语法如下:
#ifdef <macro>
……
#else
……
#endif - 根据宏的值,其语法如下:
#if <macro>
……
#else
……
#endif
结构体
在实际的处理对象中,有许多信息是由多个不同类型的数据组合在一起进行描述,而且这些不同类型的数据是互相联系组成了一个有机的整体。此时,就要用到一种新的构造类型数据——结构体(structure),简称结构。
定义一个结构体类型的一般形式为:
struct 结构体名
{
数据类型 成员名1;
数据类型 成员名2;
...
数据类型 成员名n;
};
举个例子:
定义一个职工worker结构体如下:
struct worker
{
long number;
char name[20];
char sex;
int age;
float salary;
char address[80];
};
int age = 10;
特点:
- 结构体类型是用户自行构造的。
- 它由若干不同的基本数据类型的数据构成。
- 它属于C语言的一种数据类型,与整型、实型相当。因此,定义它时不分配空间,只有用它定义变量时才分配空间。
定义结构体变量方法
1.先定义结构体类型再定义变量名
这是C语言中定义结构体类型变量最常见的方式
struct 结构体名
{
成员列表;
};
struct 结构体名 变量名;
举个例子:
truct worker
{
long number;
char name[20];
char sex;
int age;
float salary;
char address[80];
char phone[20];
};
struct worker worker1,worker2;
2.在定义类型的同时定义变量
struct 结构体名
{
成员列表;
}变量名;
3.直接定义结构类型变量
其一般形式为:
struct //没有结构体名
{
成员列表;
}变量名
结构体的大小
使用sizeof来求
sizeof(struct worker)
sizeof(worker1)
补充一个知识点,就是结构体的大小求解中的两个原则:
- 不但结构体的成员有有效对齐值,结构体本身也有对齐值,这主要是考虑结构体的数组,对于结构体或者类,要将其补齐为其有效对齐值的整数倍。结构体的有效对齐值是其最大数据成员的自身对齐值;
- 存放成员的起始地址必须是该成员有效对齐值的整数倍。
对于每个对齐值有如下定义:
- 自身对齐值: 数据类型本身的对齐值,例如char类型的自身对齐值是1,short类型是2;
- 指定对齐值: 编译器或程序员指定的对齐值,32位单片机的指定对齐值默认是4;(整个结构体的长度需要是默认对齐的整数倍)
- 有效对齐值: 自身对齐值和指定对齐值中较小的那个。
举个例子:
struct ep{
char a;
int b;
char c;
char d;
};
首先a在第一个字节,而b因为自身长度为4,所以其实地址在低四个字节,占据四个字节此时长度为8个字节,两个char再占用两个字节,所以数据域长度为10
个字节,由于ep自身的对齐值为4,所以最终应该为12
个字节。
结构体变量的使用形式
结构体变量的成员用一般形式表示:结构体变量名.成员名
例如:worker1.number;worker1.name;worker1.sex;
在定义了结构体变量后,就可以用不同的赋值方法对结构体变量的每个成员赋值。例如:
strcpy(worker1.name,”Zhang San”);
worker1.age=26;
strcpy(worker1.phone,”1234567”);
worker1.sex=’m’;
结构体变量的初始化
struct 结构体名 变量名={初始数据表};
或者:
struct 结构体名
{
成员列表;
}变量名={初始数据表}
结构体数组
具有相同结构体类型的结构体变量也可以组成数组,称它们为结构体数组。结构体数组的每一个数组元素都是结构体类型的数据,它们都分别包括各个成员(分量)项。
定义
定义结构体数组的方法和定义结构体变量的方法相仿,只需说明其为数组即可。与上面的结构体的定义类似。
举个例子
struct
{
char name[20];
char sex;
int age;
char addr[20];
}stu[3];
struct student
{
char name[20];
char sex;
int age;
char addr[20];
}stu[3];
struct student
{
char name[20];
char sex;
int age;
char addr[20];
};
struct student stu[3];
初始化
struct 结构体名
{
成员列表;
};
struct 结构体名 数组名[元素个数]={初始数据表};
使用
1.引用某一元素中的成员。
stu[1].name
2.一个元素赋给另外一个
student1=stu[0];
stu[0]=stu[1];
stu[1]=student1;
注意:字符串类型的不能直接等于赋值!!但是结构体可以直接赋值,虽然里面有字符串类型。
结构体指针
定义:
struct 结构体名 *结构指针名;
访问元素:
(*p).name
p->name
两者是完全等价的。
共用体
不同数据类型的数据可以使用共同的存储区域,这种数据构造类型称为共用体,简称共用,又称联合体(union)。
定义
union 共用体名
{
成员表列;
};
例如
union gy
{
int i;
char c;
float f;
};
因为每个成员长度是不一样的,从内存的角度占用的空间是所有元素中最大的。
赋值
a.i = 1;
a.c = 'a';
a.f = 1.5;
因为内存区域是公用的关系,在保存结束a.f
之后,其他的都已经没有意义,因为相关的内存的区域会被覆盖掉,数据就会发生变化。
在程序中经常使用结构体与共用体相互嵌套的形式。
struct datas
{
char *ps;
int type;
union
{
float fdata;
int idata;
char cdata;
}udata;
};
typedef 改名
在C语言中,允许使用关键字typedef定义新的数据类型
其语法如下:
typedef <已有数据类型> <新数据类型>;
例如:
typedef int INTEGER;
此时:INTEGER i;
等价于 int i;
在C语言中经常在定义结构体类型的时使用typedef
typedef struct _node_
{
int data;
struct _node_ *next;
} listnode, *linklist;
这里定义了两个新的数据类型listnode和linklist。其中listnode
等价于数据类型struct node 而 linklist等价于struct node *