1
结构体,联合体,枚举与
typedef
1.1
结构体
1.1.1
定义结构体
struct
和初始化
代码:
#include
/*
定义一个结构体
*/
struct student //定义结构体,用struct
{
char name[100];
int age;
int sex;
};
int main()
{
/*
定义一个学生st1
*/
struct student st1;
strcopy(st1.name , "crystal");
st1.age = 20;
st1.sex = 1;
/*
定义一个学习st2
与上面两种方法相同
*/
struct student st2 = { "inx",30, 0 };//在定义的同埋初始化 ,属性顺序要按照定义的顺序 ,不能打乱
struct student st3 = { .age = 20 ,.sex = 1,.name = "yinxiong" };//属性顺序可以打乱
struct student st3 = { 0};//定义一个学生属性都为空
}
结构体可以自定义成员的位长
struct D
{
char c : 2;//指定结构体的元素c 的位长为 2 ,即只占两个位, 最大
int i : 2;
};
1.1.2
访问结构体成员
.
操作符
1.1.3
结构体的内存对齐模式
编译器在编译一个结构的时候采用内存对齐模式
struct man
{
char a;
int b;
}
1.1.4
指定结构体元素的位字段
定义一个结构体的时候可以指定具体元素的位长
struct D
{
char c : 2//指定结构体的元素c 的位长为 2 ,即只占两个位, 最大11
};
1.1.5
结构数组
struct student sts[10] = { st1,st2,st3... };//定义一个结构体数组
按结构体中的一两个属性来排序:
代码:
#include
struct student
{
char name[100];
int age;
float heigh;
};
int main()
{
struct student s1 = {"inx1", 34, 181.1 };
struct student s2 = {"inx2", 21, 200.1};
struct student s3 = { "inx3", 21, 123.2 };
struct student s4 = { "inx4", 21 ,152.23 };
struct student s5 = { "inx5",26, 178.2 };
struct student s6 = { "inx6", 23,198.1 };
struct student s7 = { "inx7",27,123.1 };
struct student st[7] = { s1,s2,s3,s4,s5,s6,s7 };
for (int i = 0; i < 7;i++)
{
printf("学生%s,年龄%d, 身高%.1f\n",st[i].name, st[i].age, st[i].heigh);
}
printf("按年龄排序,年龄相同按身高排序\n");
for (int i = 0; i < 7;i++)
{
for (int j = 0; j < 6 - i;j++)
{
if (st[j].age > st[j + 1].age)
{
struct student tmp = st[j];
st[j] = st[j + 1];
st[j + 1] = tmp;
}
else if (st[j].age == st[j + 1].age)
{
if (st[j].heigh < st[j + 1].heigh)
{
struct student tmp = st[j];
st[j] = st[j + 1];
st[j + 1] = tmp;
}
}
}
}
for (int i = 0; i < 7;i++)
{
printf("学生%s,年龄%d, 身高%.1f\n", st[i].name, st[i].age, st[i].heigh);
}
}
1.1.6
嵌套结构
一个结构的成员还可以是另一个结构类型
1.1.7
结构体的赋值
代码:
sturct A
{
int a;
}
int main()
{
struct A d1 = {1};
struct A d2;
printf("d1.a=%d\n", d1.a);
//d2 = d1;
memcpy(&d2, &d1, sizeof(d1));//与 d2 = d1; 是等价的
printf("d2.a=%d\n", d2.a);
struct A *p = &d1; //定义一个A结构体类型的指针 ,并让它指向d1 的地址
//(*p).a = 10;
p->a = 10;//与(*p).a = 10;等价,前者常用
printf("d1.a=%d\n", d1.a);
return 0;
}
1.1.8
指向结构体的指针
–>
操作符
p -> a =10; //
(*p).a = 10;等价 意思是将10 赋给 p 指向的结构体的a成员
1.1.9
指向结构体数组的指针
#include
#include
/*
定义一个结构体
*/
struct student //定义结构体,用struct
{
char name[10];
int age;
float higth;
};
struct D
{
char c : 2;//指定结构体的元素c 的位长为 2 ,即只占两个位, 最大11
int i : 2;
};
struct A
{
int a;
};
int main()
{
struct A *p ;
p = malloc(sizeof(struct A) * 10);//定义一块内存 在堆中定义的 //
memset(p, 0, sizeof(struct A) * 10);//初始化内存的值都为0;
//struct A ar[0] = {0}; //定义一个数组,存在栈中
struct A *ar = p;
for (int i = 0; i < 10;i++)
{
p++->a = i;
printf("ar[%d] = %d\n", i, ar[i].a);
}
free(ar);
return 0;
}
1.1.10
结构中的数组成员和指针成员
一个结构中可以有数组成员,也可以有指针成员,如果是指针成员结构体成员在初始化和赋值的时候就需要提前为指针成员分配内存。
struct student st = { "殷雄",0 };//定义进就要给指针初始化,分配内存,
1.1.11
在堆中创建的结构体
如果结构体有指针类型成员,同时结构体在堆中创建,那么释放堆中的结构体之前需要提前释放结构体中的指针成员指向的内存。
struct man
{
char *name;
int age;
};
struct man *s = malloc(sizeof(struct man) * 2);
s[0].name = malloc(10 * sizeof(char));
s[1].name = malloc(10 * sizeof(char));
1.1.12
将结构作为函数参数
将结构作为函数参数相当值传递,函数不能改变实参的值
将结构指针作为函数参数,才能改变实参的值
在定义一个和结构有关的函数,到底是使用结构,还是结构的指针?
一般情况下将结构指针的作为参数,代码效率较高
指针作为参数,只需要传递一个地址,所以代码效率高
结论就是当一个结构做为函数的参数时候,尽量使用指针,而不是使用结构变量,这样代码效率很高
void print_student(const struct student *s)//一般来讲,不要把结构变量做为函数的参数传递
{
printf("name = %s, age = %d\n", s->name, s->age);
}
void set_student(struct student *s, const char *name, int age)
{
strcpy(s->name, name);
s->age = age;
}
1.2
联合体
联合
union
是一个能在同一个存储空间存储不同类型数据的类型。
联合体所占的内存长度等于其最长成员的长度,也有叫做共用体。
联合体虽然可以有多个成员,但同一时间只能存放其中一种。
union variant{
int ivalue;
char cvalue;
double dvalue;
};
int main()
{
union variant var;
var.cvalue = 12;
printf("%d\n", var.ivalue);
printf("%p, %p, %p\n", &(var.cvalue), &(var.ivalue), &(var.dvalue));
return 0;
}
1.3
枚举类型
1.3.1
枚举定义
可以使用枚举
(enumerated type)
声明代表整数常量的符号名称,关键字
enum
创建一个新的枚举类型。
实际上,
enum
常量是
int
类型的。
enum spectrum { red, yellow, green, blue, white, black };
enum spectrum color;
color = black;
if (color != red)
1.3.2
默认值
默认时,枚举列表中的常量被指定为
0,1,2
等
enum spectrum { red, yellow, green, blue, white, black };
printf("%d, %d\n", red, black);//0,5
指定值
可以指定枚举中具体元素的值,后面的值都会跟着改变
enum spectrum { red = 10, yellow = 20, green, blue, white, black };
printf("%d, %d\n", red, black);
1.4
typedef
typedef
是一种高级数据特性,它能使某一类型创建自己的名字
typedef unsigned char BYTE
1
与
#define
不同,
typedef
仅限于数据类型,而不是能是表达式或具体的值
2typedef
是编译器处理的,而不是预编译指令
3typedef
比
#define
更灵活
直接看
typedef
好像没什么用处,使用
BYTE
定义一个
unsigned char
。使用
typedef
可以增加程序的可移植性。
1.5
通过
typedef
定义函数指针
typedef const char *(*SUBSTR)(const char *, const char *); //定义一个函数指针类型
const char *getsubstr(const char *src, const char *str)
{
return strstr(src, str);
}
const char *func(const char *(*s)(const char *, const char *), const char *src, const char *str)