结构体
一种能包含多种数据类型,存在变量间联系,并保持数据独立的神奇类型。
1.结构布局
* 结构布局即建立一个模版。之后使用这个模版(自定义多个变量),快捷创建一组变量。
*实例:学生信息管理系统,将一个学生的信息存储在一个结构体中,将所有的结构体放到一个结构体中。
struct book{
char title[15];
char author[30];
int num;
float value;
};//注意这里还有一个分号
*book为一个结构标记,即所做结构布局的名字。后期定义可直接用book代替这些变量类型。
ps:1.结构布局只是告诉系统,需要配置一组什么类型的变量块,实际作用相当于定义了一种新的变量类型
ps:2.结构布局时不占用系统内存,只有结构被定义时,才会分配内存
ps:3.结构布局不能被初始化,它只是一个数据类型
ps:4.结构布局要定义在主函数外部,这样其他的函数才能,获取对应类型,分配相应内存
2.声明与定义
struct {
char title[15];
char author[30];
int num;
float value;
}library;//基础定义
struct book{
char title[15];
char author[30];
int num;
float value;
}library;//完整定义
struct book library;//简化定义
ps:1.如需多次使用模版,需要使用标记形式
3.初始化
struct book library={
"abppel","shdjhsk",
35,
15.23};//按顺序依次定义
struct book library={
.title="abppel",
"shdjhsk",//对于紧跟其后的值,可以省略名称
.valude=15.23};//选择特定对象定义
ps:1.初始化的值必须是常量
ps:2.每个部分用逗号隔开,行数随意选择
ps:3.结构的初始化器,可以选择特定的部分进行初始化
4.访问
printf("%s",library.author);
printf("%d",library.num);
ps:1.使用成员运算符(.),进行对结构成员的访问。
5.结构数组
- 由结构体为元素,构成的数字
struct book{
char title[15];
char author[30];
int num;
float value;
};
int main(void)
{
struct book library[50];//创建结构的数组
int i;
for(i=0 ; i<50 ; i++)//循环一次,输入一个结构体
{
scanf(*****);
scanf(*****);
scanf(*****);//对应类型的输入
}
printf("%d",library[34].num);//访问与输出
return 0;
}
ps:1.数组名称,代表数组中第一个结构体的地址。
ps:2.结构数组在内存中也是连续储存的。
6.嵌套结构
- 结构体套结构体
struct name{
char firstname[10];
char lastname[10];
};
struct people{
int age;
char country[25];
struct name mz;
};
int main(void)
{
struct people a = {
19,"England",
{"Tom","Humphrey"}
};
printf("first name is %s.",people.mz.firstname);
return 0;
}
ps:1.注意嵌套结构体访问时的顺序—由大到小
ps:2.访问时要使用变量名,而不是类型名
7.指向结构的指针
struct name{
char firstname[10];
char lastname[10];
};
struct people{
int age;
char country[25];
struct name mz;
};
int main(void)
{
struct people* x;//声明一个结构体指针
struct people a = {
19,"England",
{"Tom","Humphrey"}
};
x = &a;//指针指向a结构体
printf("first name is %s.",(*x).mz.firstname);
printf("first name is %s.",x->mz.firstname);
return 0;
}
ps:1.指针的优势,提高程序效率
ps:2.结构数组在内存中也是连续储存的,可以使用指针的运算
ps:3.只有当使用指针时,才能用 ->符号
8.结构体与函数
#include<stdio.h>
#include<string.h>
struct name{
char firstname[10];
char lastname[10];
};
struct people{
int age;
char country[25];
struct name mz;
};
struct people hs(struct people );//声明两个函数 函数可以传递
void zz(struct people *);
int main(void)
{
struct people* x;
struct people c;
struct people a = {
19, "England",
{ "Tom", "Humphrey" }
};
x = &a;
zz(x);
c = hs(a);//结构体可以相互转换
printf("%s", c.country);
printf("%s", c.mz.firstname);
return 0;
}
struct people hs(struct people b)
{
strcpy(b.country,"China");//使用string.h进行字符串变更
strcpy(b.mz.firstname, "Jam");
return b;
}
void zz(struct people * x)
{
printf("first name is %s.", x->mz.firstname);
}
ps:1.结构体(结构体数组)可以作为参数,在函数间传递
ps:2.结构体中字符串需要用string.h进行变更
ps:3.结构体可以相互赋值
ps:4.函数参数使用指针或结构体本身各有优缺点
分类 指针 结构体 优势 响应迅速,效率高 清晰明了,符合思维 缺陷 数据可能意外修改 占用较大内存 ps:5.建议const + 指针,作为参数进行传递
9.匿名结构
struct person {
int id;
struct { char first[10]; char second[10]; };//匿名结构
};
int main(void)
{
struct person std = { 7632298, { "jok", "Humphrey" } };
printf("%s", std.second);//调用匿名内容
return 0;
}
ps: 匿名结构在结构体的嵌套中使用,内部的结构体可以不加结构标记,在调用中可以直接调用
10.typedef
- 用途一:
定义一种类型的别名,而不只是简单的宏替换。可以用作同时声明指针型的多个对象
char* pa, pb; // 这多数不符合我们的意图.
// 它只声明了一个指向字符变量的指针,和一个字符变量;
typedef char* PCHAR; // 一般用大写
PCHAR pa, pb; // 可行,同时声明了两个指向字符变量的指针
char *pa, *pb;
//虽然:也可行,但相对来说没有用typedef的形式直观,尤其在需要大量指针的地方,typedef的方式更省事。
- 用途二:
用在旧的C的代码中(具体多旧没有查),帮助struct。
struct tagPOINT1
{
int x;
int y;
};
struct tagPOINT1 p1;
typedef struct tagPOINT
{
int x;
int y;
}POINT;
POINT p1; // 这样就比原来的方式少写了一个struct,比较省事,尤其在大量使用的时候
- 用途三:
为复杂的声明定义一个新的简单的别名。
ps:用typedef 声明的量,其实相当于一个新的数据类型