1.结构体
1.概念
将基本类型或构造类型封装在一起,拥有独立空间,这个数据结构 就叫结构体。
结构体 使用的关键字
struct.
一个结构体可以定义多个结构体变量
2.定义
注意:
1,结构体定义一般在头文件中
2,不要在定义结构体时给其成员初始化
方式一:
struct 结构体名称
{
成员
};
定义结构体变量:
struct 结构体名称 结构体对象名
;
特点
将定义结构体与定义结果体变量分开
示例:
struct stu
{
char name[50];
char sex[5];
int age;
};
void fun01()
{
struct stu s1;
}
方式二:
语法:
struct 结构体名称
{
成员
}结构体变量名;
特点
定义结构体同时定义一个结构体变量
示例
struct stu
{
char name[50];
char sex[5];
int age;
} s1;
方式三:
语法:
struct
{
成员
}结构体变量名;
特点
该结构体变量只有一个,我们将其称为一次性结构体
示例:
struct
{
char name[50];
char sex[5];
int age;
} s1;
初始化
语法:
struct
结构体名称 结构体变量名
= {
值
1,
值
2,
值
3};
结构体对象清
0
memset(&
结构体变量名
,0,sizeof(struct
结构体名称
));
注意:
1,
结构体初始化 必须准许成员顺序和成员自身类型
2,
定义与初始化必须同时进行
使用
获取结构体成员
结构体变量名
.
成员变量名
赋值
普通类型
结构体变量名.成员变量名
=
值
;
字符数组
strcpy(结构体变量名.
成员变量名
,
值
);
整体赋值
结构体变量名1 = 结构体变量名
2;
使用memcpy
内存拷贝
memcpy(目标结构体变量地址,
原结构体变量地址
,
长度
);
示例:
struct
stu s1
=
{
"
张桑
"
,
"
男
"
,
18
};
struct
stu s2
=
s1
;
s2
.
age
=
20
;
struct
stu s3
;
memcpy
(
&
s3
,
&
s1
,
sizeof
(
struct
stu
));
s3
.
age
=
21
;
printf
(
"%s\n"
,
s1
.
name
);
printf
(
"%s\n"
,
s1
.
sex
);
printf
(
"%d\n"
,
s1
.
age
);
printf
(
"%s\n"
,
s2
.
name
);
printf
(
"%s\n"
,
s2
.
sex
);
printf
(
"%d\n"
,
s2
.
age
);
printf
(
"%s\n"
,
s3
.
name
);
printf
(
"%s\n"
,
s3
.
sex
);
printf
(
"%d\n"
,
s3
.
age
);
注意:
每个结构体变量都有其独立的内存
,
互不干扰
typedef与结构体
作用
:
简化结构体
语法
typedef struct
结构体名
{
成员
}
别名
;
示例:
typedef struct
dog
{
char
name
[
50
];
char
sex
[
5
];
int
age
;
}
Dog
;
void
fun08
()
{
Dog d1
=
{
"
旺财
"
,
"
公
"
,
2
};
Dog d2
=
{
"
富贵
"
,
"
母
"
,
1
};
printf
(
"%s %s %d\n"
,
d1
.
name
,
d1
.
sex
,
d1
.
age
);
printf
(
"%s %s %d\n"
,
d2
.
name
,
d2
.
sex
,
d2
.
age
);
Dog
*
p
= &
d1
;
printf
(
"%s %s %d\n"
,
p
->
name
,
p
->
sex
,
p
->
age
);
strcpy
(
p
->
name
,
"
黑豹
"
);
printf
(
"%s %s %d\n"
,
p
->
name
,
p
->
sex
,
p
->
age
);
}
结构体指针变量
定义
struct 结构体名称 *指针变量名 = &结构体变量;
操作语法
指针变量名->成员名称
示例1
void
fun03
()
{
struct
stu s1
=
{
"
小明
"
,
"
男
"
,
18
};
struct
stu
*
p
= &
s1
;
printf
(
"%s %s %d\n"
,(
*
p
).
name
,(
*
p
).
sex
,(
*
p
).
age
);
printf
(
"%s %s %d\n"
,
p
->
name
,
p
->
sex
,
p
->
age
);
strcpy
(
p
->
name
,
"
大明
"
);
printf
(
"%s %s %d\n"
,
p
->
name
,
p
->
sex
,
p
->
age
);
}
示例2堆区申请内存
void
fun04
()
{
struct
stu
*
p
=
(
struct
stu
*
)
calloc
(
1
,
sizeof
(
struct
stu
));
printf
(
"%s %s %d\n"
,
p
->
name
,
p
->
sex
,
p
->
age
);
strcpy
(
p
->
name
,
"
大明
"
);
strcpy
(
p
->
sex
,
"
女
"
);
p
->
age
=
18
;
printf
(
"%s %s %d\n"
,
p
->
name
,
p
->
sex
,
p
->
age
);
}
结构体数组
定义
struct 结构体名称 数组名[长度];
初始化
struct
结构体名称 数组名
[
长度
] = {{
成员值
1,
成员值
2,..},{
成员值
1,
成员值2,..},...};
示例1
struct person
{
char name[50];
char sex[5];
int age;
};
void fun05()
{
struct person persons[] = {{"张三
","
男
",18},{"
李四
","
女
",20},{"
小红","
女
",19}};
int len = sizeof(persons)/sizeof(struct person);
for(int i = 0; i < len; i++)
{
printf("%s %s %d\n",persons[i].name,persons[i].sex,persons[i].age);
}
}
示例2
struct
person
{
char
name
[
50
];
char
sex
[
5
];
int
age
;
};
void
fun06
()
{
struct
person ps
[
3
];
memset
(
ps
,
0
,
sizeof
(
ps
));
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
scanf
(
"%s %s %d"
,
ps
[
i
].
name
,
ps
[
i
].
sex
,
&
ps
[
i
].
age
);
}
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
printf
(
"%s %s %d\n"
,
ps
[
i
].
name
,
ps
[
i
].
sex
,
ps
[
i
].
age
);
}
}
示例3
void
fun07
()
{
struct
person
*
ps
=
(
struct
person
*
)
calloc
(
3
,
sizeof
(
struct
person
));
memset
(
ps
,
0
,
sizeof
(
ps
));
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
scanf
(
"%s %s %d"
,
ps
[
i
].
name
,
ps
[
i
].
sex
,
&
ps
[
i
].
age
);
}
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
printf
(
"%s %s %d\n"
,
ps
[
i
].
name
,
ps
[
i
].
sex
,
ps
[
i
].
age
);
}
}
指针变量作为结构体成员
注意
:
不要操作结构体变量中未初始化指针
示例
typedef struct cat
{
char *name;
int age;
}Cat;
void fun09()
{
//1,
不要操作结构体变量中未初始化指针
//
定义结构体变量
,
但不初始化
,
此时其中的指针为野指针
// Cat c1;
// printf("%s\n",c1.name);
//
定义结构体变量
,
使用
memset
清
0,
此时其中的指针为空指针
Cat c2;
memset(&c2,0,sizeof(c2));
printf("%s\n",c2.name);
}
指针成员初始化
void fun10()
{
Cat c = {"布丁
",2};
printf("%s\n",c.name);
}
//
注意
:
此时结构体变量
c
中指针成员指向文字常量区
,
此时不能修改其指向地址中的值
,只能读取或修改其指向的地址
指针成员堆区初始化
void fun11()
{
Cat c;
c.name = (char *)malloc(50);
strcpy(c.name,"tom");
c.age = 2;
printf("%s\n",c.name);
c.name[0] = 'T';
printf("%s\n",c.name);
if (c.name != NULL)
{
free(c.name);
c.name = NULL;
}
}
//
使其指针成员指向堆区
,
那么就可以对其进行读写
结构体指针变量堆区初始化
,
指针成员堆区初始化:
void fun12()
{
/*
1,
先在堆区初始化结构体指针变量
2.
然后在堆区初始化成员指针变量
3,...
4,
释放成员指针变量堆区空间
5,
释放结构体指针变量堆区空间
*/
Cat *c = (Cat *) malloc(sizeof(Cat));
c->age = 3;
c->name = (char *)malloc(20);
strcpy(c->name,"布丁
");
printf("%s %d\n",c->name,c->age);
if (c->name != NULL)
{
free(c->name);
c->name = NULL;
}
if (c != NULL)
{
free(c);
c = NULL;
}
}
结构体指针数组堆区初始化
,
结构体指针变量堆区初始化
,
指针成员堆区初始化
void fun13()
{
/*
1,
先在堆区初始化结构体指针数组
2,
再在堆区初始化结构体指针变量
3.
然后在堆区初始化成员指针变量
3,...
4,
释放成员指针变量堆区空间
5,
释放结构体指针变量堆区空间
6,
释放结构体指针数组堆区空间
*/
Cat **cs = (Cat **) calloc(3,sizeof(Cat *));
for(int i = 0; i < 3; i++)
{
Cat *c = (Cat *)malloc(sizeof(Cat));
c->name = (char *)malloc(20);
scanf("%s %d",c->name,&(c->age));
cs[i] = c;
}
for(int i = 0; i < 3; i++)
{
printf("%s %d\n",cs[i]->name,cs[i]->age);
if (cs[i]->name != NULL)
{
free(cs[i]->name);
cs[i] = NULL;
}
if (cs[i] != NULL){
free(cs);
cs[i] = NULL;
}
}
if (cs != NULL)
{
free(cs);
cs = NULL;
}
}
浅拷贝
:
拷贝地址
typedef struct test01
{
char *str;
} Test01;
void fun14()
{
Test01 t01;
t01.str = (char *) malloc(20);
strcpy(t01.str,"德玛西亚
");
Test01 t02;
t02 = t01;//此时
t02
的中
str
与
t01
中的
str
指向同一堆区地址
,
发生浅拷贝
printf("t01.str = %s\n",t01.str);
printf("t02.str = %s\n",t02.str);
strcpy(t02.str,"艾欧尼亚
");
printf("t01.str = %s\n",t01.str);
printf("t02.str = %s\n",t02.str);
//
当释放是会产生错误
if (t01.str != NULL)
{
free(t01.str);
t01.str = NULL;
}
if (t02.str != NULL)
{
free(t02.str);
t02.str = NULL;
}
}
深拷贝:
拷贝内容
void fun15()
{
Test01 t01;
t01.str = (char *) malloc(20);
strcpy(t01.str,"德玛西亚
");
Test01 t02;
t02.str = (char *) malloc(20);
strcpy(t02.str,t01.str);//深拷贝
printf("t01.str = %s\n",t01.str);
printf("t02.str = %s\n",t02.str);
strcpy(t02.str,"艾欧尼亚
");
printf("t01.str = %s\n",t01.str);
printf("t02.str = %s\n",t02.str);
if (t01.str != NULL)
{
free(t01.str);
t01.str = NULL;
}
if (t02.str != NULL)
{
free(t02.str);
t02.str = NULL;
}
}