1)结构体类型的定义
2)结构体变量的定义
3)结构体变量的初始化
4)typedef 改类型名
typedef struct Teacher
{
char name[50];
int age;
}Teacher1;
5)点运算符和指针法操作结构体
6)结构体也是一种数据类型,复合类型(自定义类型)
//结构体类型定义
//struct 关键字,struct Teacher 合在一起才是类型
//{} 后面有分号
struct Teacher
{
char name[50];
int age;
};
//结构体变量定义,全局变量
struct Teacher t;
int main()
{
//结构体变量定义,局部变量
struct Teacher t2={"lili",18};
printf("%s %d\n",t2.name,t2.age);
strcpy(t2.name,"xiaoming");
t2.age=22;
struct Teacher *p=NULL; //指针指向空,无法对其成员进行操作
p=&t2;
strcpy(p->name,"xiaoming");
p->age=22; //等价于:(*p).age=22;
printf("%s %d\n",p->name,p->age);
return 0;
}
//定义结构体类型时。不要直接给成员赋值
//结构体只是一个类型,还没有分配空间
//只有根据类型定义变量时,才分配空间,有空间后才能赋值
typedef struct Teacher
{
char name[50];
//int age=50; //err
int age;
}Teacher;
void copyTeacher(Teacher to,Teacher from)
{
to=from;
}
void copyTeacher1(Teacher *to,Teacher *from)
{
*to=*from;
}
int main()
{
Teacher t1={"lily","22"};
//相同类型的两个结构体变量,可以相互赋值
//把 t1 成员变量内存的值拷贝给 t2 成员变量的内存
//t1 和 t2 在内存上没有关系,类似于:int a=10; int b=a;
Teacher t2=t1;
printf("%s %d\n",t2.name,t2.age); //lily 22
Teacher t3;
memset(&t3,0,sizeof(t3));
copyTeacher(t3,t1); //t1 拷贝给 t3
printf("%s %d\n",t3.name,t3.age); // 0 值传递
copyTeacher1(&t3,&t1); //t1 拷贝给 t3
printf("%s %d\n",t3.name,t3.age); // lily 22 地址传递
return 0;
}
1)结构体静态数组
typedef struct Teacher
{
char name[50];
int age;
}Teacher;
int main()
{
//结构体数组初始化方法1:
Teacher a[3]=
{
{"a",18},
{"a",18},
{"a",18}
};
//结构体数组初始化方法2:
//这种属于是静态结构体数组
Teacher b[3]={"a",18,"a",18}; //剩下没有赋值的部分会自动初始化为 0
for(int i=0;i<3;i++)
{
printf("%s %d\n",b[i].name,b[i].age);
}
return 0;
}
2)结构体动态数组
typedef struct Teacher
{
char name[50];
int age;
}Teacher;
int main()
{
//类似于:Teacher p[3];
Teacher* p=(Teacher*)malloc(3*sizeof(Teacher));
if(p==NULL)
return -1;
char buf[50];
for(int i=0;i<3;i++)
{
sprintf(buf,"name%d%d%d\n",i,i,i);
strcpy(p[i].name,buf);
p[i].age=20+i;
}
for(int i=0;i<3;i++)
{
printf("%s %d\n",p[i].name,p[i].age);
}
if(p!=NULL)
{
free(p);
p=NULL;
}
return 0;
}
1)结构体套一级指针
typedef struct Teacher
{
char *name;
int age;
}Teacher;
int main()
{
char* name=NULL;
//strcpy(name,"lily"); //err,因为 name 指向空,无法对其进行拷贝
name=(char*)malloc(sizeof(char)*30);
strcpy(name,"lily");
if(name!=NULL)
{
free(name);
name=NULL;
}
//1.
Teacher t;
t.name=(char*)malloc(sizeof(char)*30);
strcpy(t.name,"lily");
t.age=22;
printf("%s %d\n",t.name,t.age); //lily 22
if(t.name!=NULL)
{
free(t.name);
t.name=NULL;
}
//2.
Tearcher *p=NULL;
p=(Teacher*)malloc(sizeof(Teacher)*1);
p->name=(char*)malloc(sizeof(char)*30);
strcpy(p->name,"lily");
p->age=22;
printf("%s %d\n",p->name,p->age); //lily 22
if(p->name!=NULL)
{
free(p->name);
p->name=NULL;
}
if(p!=NULL)
{
free(p);
p=NULL;
}
//3.
Teacher *q=NULL;
q=(Teacher*)malloc(sizeof(Teacher)*3); //Teacher q[3];
char buf[30];
for(int i=0;i<3;i++)
{
q[i].name=(char*)malloc(sizeof(char)*30);
sprintf(buf,"name%d%d%d",i,i,i);
strcpy(q[i].name,buf);
q[i].age=20+i;
}
for(int i=0;i<3;i++)
{
printf("%s %d\n",q[i].name,q[i].age);
}
for(int i=0;i<3;i++)
{
if(q[i].name!=NULL)
{
free(q[i].name);
q[i].name=NULL;
}
}
if(q!=NULL)
{
free(q);
q=NULL;
}
return 0;
}
typedef struct Teacher
{
char *name;
int age;
}Teacher;
void showTeacher(Taecher *q,int n)
{
int i=0;
for(i=0;i<n;i++)
{
printf("%s %d\n",q[i].name,q[i].age);
}
}
void freeTeacher(Teacher *q,int n)
{
int i=0;
for(int i=0;i<3;i++)
{
if(q[i].name!=NULL)
{
free(q[i].name);
q[i].name=NULL;
}
}
if(q!=NULL)
{
free(q);
q=NULL;
}
}
Teacher* getMem(int n)
{
Teacher *q;
q=(Teacher*)malloc(sizeof(Teacher)*n); //Teacher q[3];
char buf[30];
for(int i=0;i<n;i++)
{
q[i].name=(char*)malloc(sizeof(char)*30);
sprintf(buf,"name%d%d%d",i,i,i);
strcpy(q[i].name,buf);
q[i].age=20+i;
}
return q;
}
int getMem1(Teacher **tmp,int n)
{
if(tmp==NULL)
return -1;
Teacher *q;
q=(Teacher*)malloc(sizeof(Teacher)*n); //Teacher q[3];
char buf[30];
for(int i=0;i<n;i++)
{
q[i].name=(char*)malloc(sizeof(char)*30);
sprintf(buf,"name%d%d%d",i,i,i);
strcpy(q[i].name,buf);
q[i].age=20+i;
}
*tmp=q;
return 0;
}
int main()
{
Teacher *q=NULL;
//q=getMem(3); //值传递,返回值
int ret=0;
ret=getMem1(&q,3); //地址传递
if(ret!=0)
return ret;
showTeacher(q,3);
freeTeacher(q,3);
q=NULL;
return 0;
}
typedef struct Teacher
{
char **stu; //一个老师有多个学生
}Teacher;
int main()
{
//1.
Teacher t;
//t.stu[3]
//char *t.stu[3]
int n=3;
int i=0;
t.stu=(char**)malloc(sizeof(char*)*n);
for(i=0;i<n;i++)
{
t.stu[i]=(char*)malloc(30);
strcpy(t.stu[i],"lily");
}
for(i=0;i<n;i++)
{
printf("%s\n",t.stu[i]);
}
for(i=0;i<n;i++)
{
if(t.stu[i]!=NULL)
{
free(t.stu[i]);
t.stu[i]=NULL;
}
}
if(t.stu!=NULL)
{
free(t.stu);
t.stu=NULL;
}
//2.
Teacher *p=NULL;
//p->stu[3]
p=(Teacher*)malloc(sizeof(Teacher));
p->stu=(char**)malloc(sizeof(char*)*n);
for(i=0;i<n;i++)
{
p->stu[i]=(char*)malloc(30);
strcpy(p->stu[i],"lily");
}
for(i=0;i<n;i++)
{
printf("%s\n",p->stu[i]);
}
for(i=0;i<n;i++)
{
if(p->stu[i]!=NULL)
{
free(p->stu[i]);
p->stu[i]=NULL;
}
}
if(p->stu!=NULL)
{
free(t.stu);
p->stu=NULL;
}
if(p!=NULL)
{
free(p);
p=NULL;
}
//3.
Teacher *q=NULL;
//Teacher q[3]
//q[i].stu[3]
q=(Teacher*)malloc(sizeof(Teacher)*n); //Teacher q[3]
for(i=0;i<n;i++)
{
(q+i)->stu=(char**)malloc(n*sizeof(char*)); //char *stu[3];
for(int j=0;j<3;j++)
{
(q+i)->stu[j]=(char*)malloc(30);
char buf[30];
sprintf(buf,"name%d%d%d",i,i,i);
strcpy((q+i)->stu[j],buf);
}
}
for(i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
printf("%s\n",(q+i)->stu[j]);
}
}
//free
for(i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
if((q+i)->stu[j]!=NULL)
{
free((q+i)->stu[j]);
(q+i)->stu[j]=NULL;
}
}
if(q[i].stu!=NULL)
{
free(q[i].stu);
q[i].stu=NULL;
}
}
if(q!=NULL)
{
free(q);
q=NULL;
}
return 0;
}
typedef struct Teacher
{
char **stu; //一个老师有多个学生
}Teacher;
//n1 老师数量,n2 每个老师的学生数量
int creatTeacher(Teacher **tmp,int n1,int n2)
{
int i=0;
if(tmp==NULL)
return -1;
Teacher *q=(Teacher*)malloc(sizeof(Teacher)*n1); //Teacher q[3]
for(i=0;i<n1;i++)
{
(q+i)->stu=(char**)malloc(n2*sizeof(char*)); //char *stu[3];
for(int j=0;j<n2;j++)
{
(q+i)->stu[j]=(char*)malloc(30);
char buf[30];
sprintf(buf,"name%d%d%d",i,i,i);
strcpy((q+i)->stu[j],buf);
}
}
//间接赋值
*tmp=q;
return 0;
}
void showTeacher(Teacher *q,int n1,int n2)
{
if(q==NULL)
{
return;
}
for(int i=0;i<n1;i++)
{
for(int j=0;j<n2;j++)
{
printf("%s\n",(q+i)->stu[j]);
}
}
}
void freeTeacher(Teacher **tmp,int n1,int n2)
{
if(tmp==NULL)
return;
Teacher *q=*tmp;
//free
for(int i=0;i<n1;i++)
{
for(int j=0;j<n2;j++)
{
if((q+i)->stu[j]!=NULL)
{
free((q+i)->stu[j]);
(q+i)->stu[j]=NULL;
}
}
if(q[i].stu!=NULL)
{
free(q[i].stu);
q[i].stu=NULL;
}
}
if(q!=NULL)
{
free(q);
q=NULL;
*tmp=NULL;
}
}
int main()
{
//3.
Teacher *q=NULL;
int ret=0;
ret=creatTeacher(&q,3,3);
if(ret!=0)
return -1;
//Teacher q[3]
//q[i].stu[3]
showTeacher(q,3,3);
freeTeacher(&q,3,3);
return 0;
}
typedef struct Teacher
{
int age;
char **stu; //一个老师有多个学生
}Teacher;
void sortTeacher(Teacher *q,int n)
{
if(q==NULL)
return -1;
int i=0;
int j=0;
Teacher tmp;
for(i=0;i<n-1;i++)
{
for(j=i+1;j<n;j++)
{
if(p[i].age<p[j].age)
{
tmp=p[i];
p[i]=p[j];
p[j]=tmp;
}
}
}
}
1)浅拷贝
typedef struct Teacher
{
char *name;
int age;
}Teacher;
int main()
{
Teacher t1;
t1.name=(char*)malloc(30);
strcpy(t1.name,"lily");
t1.age=22;
Teacher t2;
t2=t1; //浅拷贝,t1.name 和 t2.name 都指向堆区的同一块内存
printf("%s %d\n",t2.name,t2.age); //lily 22
//释放
if(t1.name!=NULL)
{
free(t1.name);
t1.name=NULL;
}
if(t2.name!=NULL) //err,由于t1.name 和 t2.name 都指向堆区的同一块内存,前面已经是放过了,这里释放的是与前面同一块内存,同一块内存释放两次,就会报错
{
free(t2.name);
t2.name=NULL;
}
return 0;
}
2)深拷贝
typedef struct Teacher
{
char *name;
int age;
}Teacher;
int main()
{
Teacher t1;
t1.name=(char*)malloc(30);
strcpy(t1.name,"lily");
t1.age=22;
Teacher t2;
//深拷贝,人为地分配内存
t2.name=(char*)malloc(30);
t2=t1; //深拷贝,此时t1.name 和 t2.name 指向堆区的不同内存
printf("%s %d\n",t2.name,t2.age); //lily 22
//释放
if(t1.name!=NULL)
{
free(t1.name);
t1.name=NULL;
}
if(t2.name!=NULL) //OK
{
free(t2.name);
t2.name=NULL;
}
return 0;
}
typedef struct Teacher
{
char name[64]; //64
int age; //4
int id; //4
}Teacher;
int main()
{
Teacher t1;
Teacher *p=NULL;
p=&t1;
int n1=(int)(&p->age)-(int)p; //64 相对于结构体首地址
int n2=&((Teacher*)0)->age; //决定 0 地址的偏移量
printf("%d\n",n2); //64
return 0;
}
1)对齐规则
struct stru1
{
int a;
short b;
double c;
}A; //对齐单位为 8 个字节,a 放在 0-7 字节内,b 放在 8-15 字节内,放不满的补齐,c 放在 16-23 字节
// A 的大小为 24 字节,sizeof(A)=24
struct stru2
{
int a; //0-7
short b; //8-15
double c; //16-23
struct stru1 B; //B 内部的每个成员也都按照以 8 字节进行对齐存储,B.a:24-31, B.b:32-39, B.c:40-48
}C; //对齐单位为 8 个字节
//结构体嵌套:以最大的成员的内存大小为单位进行对齐,
2)指定对齐单位
#pragma pack(2) //指定对其单位为 2 个字节
struct stru1
{
int a; //以两个单位来对齐
short b; //以一个单位来对齐
double c; //以四个单位来对齐
}A;
3)不完整类型的字节对齐:位域
struct A
{
int a1:5; //a1 指定位域宽度为 5 位
int a2: //a2 指定位域宽度为 9 位
char c;
int b:4;
short s;
}B; //sizeof(b)=16
//a1+a2=14 位,少于32 位,占据32位,即 4 字节
//c,也需要 4 字节
// b,占 4 位,少于32 位,占据32位,即 4 字节
// s,也需要 4 字节
//共 16 字节