目录
一、结构体
结构体类型 ---- 用来描述复杂数据的一种数据类型
//构造类型 //用户自定义类型
1.语法
struct 结构体名
{
成员列表;
} ;
(1) struct 关键字
表示 是在构造一个结构体的类型
(2) 结构体名
用来 描述 结构体这个类型 一个名称
(3) 成员列表
表示 要描述的复杂数据 中用到的 具体的成员变量
定义的方式,与之前变量的方式相同
多个成员变量之间,用分号隔开。
(4) 最后 有一个 分号 表示 结束
eg:
struct student
{
char name[10];
int sno;
float score;
char sex;
}; //表示 定义出 一个 数据类型
注意:
(1).结构体类型的使用的过程
a.先定义出类型
b.定义变量
(2).定义变量
struct 结构体名 变量名;
eg:struct student s;
同类型的结构体变量之间 ,可以相互赋值
struct student s1;
struct student s2;
s2 = s1;
结构体类型的定义形式:
//形式1 先定义类型,然后定义变量
struct demo
{};
struct demo d;
//形式2 定义类型的同时,定义变量
struct demo
{
}d; //如果结构体写在全局区域,此时的d是全局变量;但如果结构体在局部,这个d就是局部变量。
//形式3 定义类型的同时,定义变量,可以省略 结构体名
struct
{
}d; //如果结构体类型只用一次
2.结构体初始化
struct student s = {};
初始化
看每个成员变量,具体是什么数据类型。
根据 各个成员变量 自身的数据类型,进行初始化。
初始化的顺序,按照定义的顺序,依次初始化
3.访问结构体变量的成员
结构体变量的引用:
//结构体数据 引用时,一般是引用到具体的成员数据
. //结构体成员运算符
使用:
结构体变量名.成员名 //表示 访问 某个结构体 的成员
-> //指向结构体成员 运算符
结构体指针->成员名
通过 结构体变量名.成员名 访问
#include <stdio.h>
struct student
{
char name[10];
char sex;
int sno;
float score;
};
struct teacher
{
char name[10];
char sex;
int salary;
char level;
};
int main(int argc, const char *argv[])
{
struct student a={"Jerry",'M',888,78.5};
struct teacher t={"Joho",'M',8500,'A'};
printf("name = %s\n",a.name);
printf("sex = %c\n",a.sex);
printf("sno = %d\n",a.sno);
printf("score = %.2f\n",a.score);
printf("----------------\n");
printf("name = %s\n",t.name);
printf("sex = %c\n",t.sex);
printf("salary= %d\n",t.salary);
printf("level = %c\n",t.level);
return 0;
}
如果有多个相同的变量,可以组成一个数组
struct student s[3]={{"Jerry",'M',1,78.5},{"Joho",'M',2,72.0},{"Wang",'F',3,75.5}};
通过结构体指针->成员名 访问
#include <stdio.h>
struct student
{
char name[10];
char sex;
int sno;
float score;
};
void input_stu_info(struct student *s,int len)
{
printf("Input a name:");
scanf("%s",s->name);
printf("Input sex:");
scanf("%hhd",&s->sex);
printf("Input a sno:");
scanf("%d",&s->sno);
printf("Input a score:");
scanf("%f",&s->score);
}
int main(int argc, const char *argv[])
{
struct student s;
input_stu_info(s,len);
printf("name = %s\n",s.name);
printf("sex = %d\n",s.sex);
printf("sno = %d\n",s.sno);
printf("score = %.2f\n",s.score);
return 0;
}
4.结构体类型的大小
1.在32位的平台上,默认都是按4字节对齐的。(整体能被4整除)
2.对于成员变量,
各自在自己的自然边界上对齐。(也就是能被它自己的字节数整除)
char -- 1字节
short -- 2字节
int -- 4字节
3.如果 成员变量中有比4字节大。
此时 整个结构体 按照4字节对齐。 //32位的平台
4.如果 成员变量中没有比4字节大。
此时 整个结构体 按照最大的那个成员对齐。
//32位的平台
//如果有超过4字节 ,按照4字节对齐
//如果没有超过4字节的,则按成员变量中最大对齐
----------------------------------------------
//64位的平台
//如果超过4字节的,按超过的最大的成员变量对齐
//如果没有超过4字节的,则按成员变量中最大对齐
-----------------------------------------------
内存对齐可以提高效率。
5.库函数中快速排序
qsort()
void qsort(
void *base, //要排序的数组的首地址
size_t nmemb, //数组元素的个数
size_t size, //单个元素的大小
int (*compar)(const void *, const void *) //比较函数 --- 提供比较依据(由用户自己书写比较规则)//这是一个函数指针,实现函数回调
);
功能:
排序数组 (这个函数任何类型的数组都可以排序,只要给一个数组)
int compar(const void *a, const void *b)
{ //比较函数
//形参 a 和 b 用来接收 要比较的两个数组元素(由于是空类型指针,所以首先需要指明类型)
}
#include <stdio.h>
#include <stdlib.h>//注意使用qsort函数需要加上此头文件
struct student
{
char name[10];
char sex;
int sno;
float score;
};
void output_stu_info(struct student *s,int len)
{
printf("%10s %3s %4s %5s\n","name|","sex|","sno|","score");
int i=0;
for(i=0;i<len;++i)
{
printf("%9s|",s[i].name);
printf("%4c|",s[i].sex);
printf("%4d|",s[i].sno);
printf("%5.2f\n",s[i].score);
}
}
int compare(const void *a,const void *b)
{
const struct student *p=a;
const struct student *q=b;//指明类型是构造的结构体类型
return (p->score)*100 - (q->score)*100;
}
int main(void)
{
struct student s[3]={{"Jerry",'M',1,78.5},{"Joho",'M',2,87.0},{"Wang",'F',3,67.5}};
qsort(s,3,sizeof(s[0]),compare);
output_stu_info(s,3);
return 0;
}
二、共用体
1.语法
union 共用体名
{
成员变量;
};
eg:
union demo
{
char a;
short b;
int c;
};
2.共用体的大小
共用了一块内存空间,共用了最大成员的空间
注意:
1.共用体初始化时,只能给一个值,默认时给到第一个成员的。
2.共用体变量中的值,取决于最后一次给到的值,还要看能覆盖几个字节。
对比 结构体
1.结构体中各个成员 拥有自己独立空间
2.共用体中,成员共用一块空间
#include <stdio.h>
union test
{
unsigned int a;
unsigned short b;
unsigned char c;
};
int main(void)
{
union test num;
num.a=0x12345678;
num.b=0xabcd;
num.c=0xef;
printf("int %#x\n",num.a);
printf("short %#x\n",num.b);
printf("char %#x\n",num.c);
return 0;
}
运行结果:
unsigned 是为了防止符号位扩展,因为输出时是十六进制的,如果符号位为1,则打印出来的会有f,如下图
可以看出ef将后两位都覆盖了,是因为电脑是小端存储,数据小的存于地址低处,所以覆盖的是后面。由此可以看出共用体共用一块内存。
int是4个字节,union共用一块地址,所以7个char依次存放,char是1个字节,但是按照内存对齐,struct整体要能被4整除,所以整块的空间是12。