头文件:#include<string.h>
//struct:结构体关键字
//stu:结构体类型名,指定了一个结构体类型,它相当于一个模型,但其中并无具体数据,系统对之也不分配实际内存单元
//使用结构体类型必须是struct stu
//num name age叫做结构体中的成员
//定义结构体类型的时候不要给成员赋值(重要)
//定义结构体类型的时候 并没有分配空间 所以不能给成员赋值
struct stu
{
int num;
char name[32];
int age;
}; //一定要记得有;号
结构体中的成员拥有独立的空间
知识点二:结构体变量的定义
struct stu
{
int num; //4B
char name [32];//32B
int age; //4B
};
void test1(void)
{
//就用结构体类型定义一个变量
struct stu lucy; //lucy 是局部变量 lucy的成员内容不确定
//通过结构体变量访问结构体中的成员(访问时一定要遵循成员自身的类型)
lucy.num = 100;
strcpy (lucy.name,"德玛西亚");
lucy.age = 18;
printf("num = %d\n",lucy.num);
printf("name = %s\n",lucy.name);
printf("age = %d\n",lucy.age);
}
知识点三:结构体变量的初始化
struct stu
{
int num; //4B
char name [32]; //32B
int age; //4B
};
void test1(void)
{
//初始化的顺序必 须和 结构体成员的顺序一致
struct stu lucy = {100,"德玛西亚",18};
printf(" num = %d,name = %s,age = %d\n", lucy.num,lucy.name,lucy.age);
//清空结构体变量
memset(&lucy,0,sizeof(lucy));
}
知识点四:结构体变量获取键盘输入
struct stu
{
int num; //4B
char name [32]; //32B
int age; //4B
};
void test1(void)
{
struct stu lucy;
memset(&lucy,0,sizeof(lucy));
printf("请输入num name_age:") ;
//&lucy.num取的是num成员地址
scanf("%d %s %d",&lucy.num,&lucy.name,&lucy.age);
printf("num = %d,name = %s,age = %d\n",lucy.num,lucy.name,lucy.age);
}
知识点五:结构体变量之间的赋值
内存拷贝
memcpy:内存块中的数据从一个地方复制到另一个地方
memcpy(void *str1, const void *str2, size_t n);
参数说明:
str1:指向用于存储复制内容的目标数组,类型强制转换为 void* 指针
str2:指向要复制的数据源,类型强制转换为 void* 指针
n:要被复制的字节数
struct stu
{
int num; //4B
char name [32]; //32B
int age; //4B
};
void test1(void)
{
struct stu lucy = {100,"小法",18} ;
struct stu bob;
//需求将lucy的值赋值bob
//方式一:逐个成员赋值
//bob.num = lucy.num;
//strcpy(bob.name,lucy.name);
//bob.age = lucy.age;
//方拾二:相同类型的结构体变量 可以直接赋值(推荐)
//bob = lucy;
//方法三:方法二的底层实现
memcpy(&bob, &lucy,sizeof(struct stu));
printf("num = %d,name = %s,age = %d\n",bob.num,bob.name,bob.age);
}
知识点六:结构体数值
struct stu
{
int num; //4B
char name [32]; //32B
int age; //4B
};
void test1(void)
{
struct stu arr[5]={
{100,"小法",18},
{101,"德玛西亚",19},
{102,"盲僧",20},
{103,"快乐风男",30},{104,"提莫",8}};
int n = sizeof(arr)/sizeof(arr[0]);
int i = 0;
for(i = 0;i < n;i++)
{
printf("num = %d,name = %s,age = %d\n",arr[i].num, arr[i].name,arr[i].age);
}
}
知识点七:冒泡排序
#include<stdio.h>
#include<stdlib.h>
void test1(void)
{
int n = 0;
int i,j = 0;
int *arr = NULL;
printf("请输入数据的个数:");
scanf ("%d",&n);
//根据元素的个数申请空间
arr = (int *)calloc(n,sizeof(int));
if(NULL == arr)
{
perror("calloc");
return;
}
//键盘给动态数组获取输入
printf("请输入%d个int数据\n",n);
for(i = 0;i < n;i++)
{
scanf("%d",arr+i);//arr+i 第i个元素的地址
}
//排序
for(i = 0;i < n-1;i++)
{
for(j = 0; j < n-i-1;j++)
{
if(arr[j] > arr[j+1]) //从小到大排列
{
int tmp = 0;
tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
}
}
//数组的遍历
for(i = 0;i < n; i++)
{
printf("%d ",arr[i]);
}
printf("\n");
//释放空间
if(arr != NULL)
{
free(arr) ;
arr = NULL;
}
}
升级版
#include<stdio.h>
#include<stdlib.h>
void test1(void)
{
int n = 0;
int i,j = 0;
int *arr = NULL;
printf("请输入数据的个数:");
scanf ("%d",&n);
//根据元素的个数申请空间
arr = (int *)calloc(n,sizeof(int));
if(NULL == arr)
{
perror("calloc");
return;
}
//键盘给动态数组获取输入
printf("请输入%d个int数据\n",n);
for(i = 0;i < n;i++)
{
scanf("%d",arr+i); //arr+i 第i个元素的地址
}
//排序
for(i = 0;i < n-1;i++)
{
int flag = 0;
for(j = 0; j < n-i-1; j++)
{
if(arr[j] > arr[j+1]) //从小到大排列
{
int tmp = 0;
tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
}
if(flag == 0) //数组已经有序
break;
}
//数组的遍历
for(i = 0;i < n; i++)
{
printf("%d ",arr[i]);
}
printf("\n");
//释放空间
if(arr != NULL)
{
free(arr);
arr = NULL;
}
}
结构体数组排序
#include<stdio.h>
#include<string.h>
struct stu
{
int num; //4B
char name [32]; //32B
int age; //4B
};
void test1(void)
{
struct stu arr[5];
int i,j = 0;
int n = sizeof (arr)/sizeof(arr[0]);
memset (arr,0,sizeof(arr)); //整个数组清0
//获取键盘输入
printf("请输入%d个学生信息\n",n) ;
for(i=0;i<n; i++)
{
scanf("%d %s %d",&arr[i].num,arr[i].name,&arr[i].age);
}
//根据学号排序
for(i = 0;i < n-1;i++)
{
for(j = 0; j < n-i-1;j++)
{
if(arr[j].num < arr[ j+1].num) //按照num的从大到小排序
{
struct stu tmp;
tmp = arr[j] ;
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
}
}
//遍 历
printf("--------------\n") ;
for(i = 0;i < n;i++)
{
printf("%d %s %d\n",arr[i].num,arr[i].name,arr[i].age);
}
}
知识点八:typedef 给已有的类型取个别名
1、给int取个别名INT32
#include<stdio.h>
// typedef使用步骤:
//1、先用已有的类型_ 定义一个变量 int num;
//2、用别名替换变量名 int INT32;
//3、在整个表达式前添加typedef typedef int INT32;
//注意:不能创造新的类型
typedef int INT32;
void test1()
{
INT32 num = 10;
printf("num = %d\n",num);//10
}
2、给数组取个别名
//ARR_TYPE 就是数组类型,该数组必须有5个元素 每个元素为int
typedef int ARR_TYPE[5];
void test1()
{
ARR_TYPE arr = {10, 20, 30, 40, 50}; //arr就是一个拥有5个元素每个元素为int的数
int i = 0;
for(i = 0;i < 5;i++)
{
printf("%d ",arr[i]);
}
printf("\n") ;
}
3、给指针取别名
typedef int *P_TYPE;
void test1()
{
int num = 10;
P_TYPE p = # //P_TYPE p == int *p
printf("*p = %d\n", *p); //10
}
4、给函数指针取别名
int my_add(int x,int y)
{
return x+y;
}
//FUN_P是一个函数指针类型 该函数必须有两个int形参以及一个int返回值
typedef int (*FUN_P)(int x, int y);
void test1()
{
FUN_P p = my_add;
printf("%d\n",p(100,200)); //300;
}
5、给结构体类型取个别名
typedef struct stu
{
int num;
char name[32];
int age;
}STU; //STU == struct stu
void test1()
{
STU lucy = {100,"lucy",18};
}
知识点九:结构体指针
typedef struct stu
{
int num;
char name[16];
int age;
}STU; //STU是结构体类型
void test1()
{
STU lucy = {100,"lucy",18};
STU *p = &lucy;
printf("num = %d,name = %s,age = %d\n",lucy.num,lucy.name,lucy.age);
//注意:如果是结构体指针需要用下面两种方式输出
printf("num = %d,name = %s,age = %d\n",(*p).num,(*p).name,(*p).age);
printf("num = %d,name = %s,age = %d\n",p->num,p->name,p->age);
printf("num = %d\n",(&lucy)->num);
}
知识点十:结构体指针作为函数的参数
#include<stdio.h>
#include<string.h>
typedef struct stu
{
int num;
char name[16];
int age;
}STU; //STU是结构体类型
void mySetSTUData(STU *p) //p=&lucy
{
printf("请输入一个学生的信息num name age\n");
scanf("%d %s %d",&p->num,p->name,&p->age);
return;
}
void myPrintSTUData(const STU *p) //tmp =lucy *p只读
{
//constSTU*p不允许用户借助p修改 p所指向的空间内容
printf("num = %d,name = %s,age = %d\n",p->num,p->name,p->age);
}
void test1()
{
STU lucy;
memset(&lucy,0,sizeof(lucy));
//定义一个函数给lucy的成员获取键盘输入
mySetSTUData(&lucy);
//定义一个函数 打印lucy的成员信息
myPrintSTUData(&lucy);
}
知识点十一:结构体内存对齐
对齐规则:
struct data
{
char c; // 1B
int i; //4B
};
void test1()
{
//结构体的大小>=成员大小之和
printf("%d\n",sizeof(struct data)); //8
struct data d;
printf("&d.c = %u\n",&d.c);
printf("&d.i = %u\n",&d.i);
}
知识点十二:结构体嵌套结构体
typedef struct
{
int x;
int y;
}DATA2;
typedef struct
{
int a;
int b;
DATA2 c; //结构体变量c作为了DATA3的成员叫结构体嵌套结构体
}DATA3;
void test1()
{
//DATA3 data = {10, 20, 30, 40};
DATA3 data = {10,20, {30,40}}; //推荐
printf("a = %d\n",data.a);
printf("b = %d\n",data.b);
printf("x = %d\n",data.c.x); //访问最底层
printf("y = %d\n",data.c.y);
}
知识点十三:结构体嵌套结构体的内存对齐
typedef struct
{
short d;
char e;
}DATA2;
typedef struct
{
short a;
int b;
DATA2 c;
char f;
}DATA;
void test1()
{
printf("%d\n", sizeof(DATA));
DATA data;
printf ("a:%u\n",&data.a);
printf("b:%u\n",&data.b);
printf("c中d: %u\n",&data.c.d);
printf("c中e: %u\n", &data.c.e);
printf("f:%u\n",&data.f);
}
知识点十四:指定对齐原则
1、使用#pragmapack改变默认对其原则
格式:#pragma pack (value) 时的指定对齐值value
注意:
1)value只能是:1248等
2)指定对齐值与数据类型对齐值相比取较小值
如:如果指定对齐值:
设为1:则short、 int、 float等均为1
设为2:则char仍为1,short为2,int变为2
步骤:
1)确定分单位:每一 -行应该分配的字节数,min(value,默认分配单位)
2)成员偏移量=成员自身类型的整数(0~n)倍
3)收尾工作=分配单位的整数(0~n) 倍
//指定对齐规则
#pragma pack(2)
typedef struct
{
char a;
int b;
short C;
}DATA1;
void test1()
{
printf ("%d\n",sizeof(DATA1)); //8
return;
}
知识点十五:位段
位段的使用
//位段 一般只考虑unsigned int类型也可以考虑unsi gned char
typedef struct
{
unsigned char a:2; //a只占一个字节中的两位二进制位
unsigned char b:2; //b只占一个字节中的两位二进制位
//相邻位域可以压缩( 压缩的位数 不能超过 成员自身大小)
unsigned char c:5;
}DATA2;
void test1()
{
printf ("%d\n",sizeof(DATA2)); //2
DATA2 data;
//位段不能取地址
//printf("%p\n",&data.a);
//位段的赋值不要操作位段的大小a:2
data.a = 6; //0110
printf("%u\n",data.a); //2
return;
}
无意义位段
typedef struct
{
unsigned char a:2; //00
unsigned char :4; //无意 义的位段( 占有两位)
unsigned char b:2; //1 1
}DATA3;
void test1()
{
DATA3 data;
memset (&data,0,1);
data.a = 0; //00
data.b = 3; //11
printf("%d\n", sizeof(DATA3));
printf("%#x\n",*(unsigned char *)&data); //1100 0000/ /0xc0 a是高位,b是低位
return;
}
应用场景
另起一个位段
typedef struct
{
unsigned char a:2; //00
unsigned char :0; //另起一个位段
unsigned char b:2; //11
}DATA4;
void test1()
{
printf ("%d\n",sizeof(DATA4));
return;
}
知识点十六:共用体与结构体的区别
结构体:struct
所有的成员拥有独立的空间
struct stu
{
char a;
short b;
int C;
}; // a b c成员有用独立的空间
共用体(联合体)union
所有的成员共享同一份空间
struct stu
{
char a;
short b;
int c;
}; // a b c成员有用共享一份空间
知识点十七:共用体
union data
{
char a;
short b;
int c;
};
void test1()
{
printf("%d\n",sizeof(union data)); //4
union data A;
A.a = 10;
A.b = 20;
A.c = 30;
printf("%d\n",A.a + A.b + A.c); //90
}
共用体虽然共有同一份空间但是从空间读取的字节数是有成员自身类型决定
union data
{
char a;
short b;
int c;
};
void test1()
{
printf("%d\n", sizeof(union data)); //4
union data A;
A.c = 0x01020304;
A.b = 0x0102;
A.a = 0x01;
printf("%#x\n",A.a+A.b+A.c);
}
知识点十八:枚举
枚举
将变量的值一一列举出来,变量的值只限于列举出来的值的范围内
枚举类型定义:
enum 枚举名
{
枚举值表
};
在枚举值表中应列出所有可用值,也称为枚举元素,枚举变量仅能取枚举值所列元素
//枚举列表的值:默认从0开始
enum POKER {HONGTAO,HEITAO=30,MEIHUA=40,FANGKUAI};
void test1()
{
//poker_ color的取值为HONGTAO,HEITAO, MEIHUA, FANGKUAI中某一个
enum POKER poker_color = HEITAO;
printf("poker_ olor = %d\n",poker_color); //30
printf("HONGTAO = %d\n",HONGTAO); //0
printf("HEITAO = %d\n",HEITAO); //30
printf("MEIHUA = %d\n",MEIHUA); //40
printf("FANGKUAI = %d\n",FANGKUAI); //41
}