结构体是一些值的变量,这些值称为成员变量,结构的每个成员都可以是不同类型的变量
struct tag
{
member-list;
}variable - list;
struct的意思是结构体关键字 tag是结构体标签(可随意替换)
member-list:意思是成员变量
struct Stu
{
char name[20];
short age;
char tele[12];
char sex[5];
};
int main()
{
struct Stu s;
return 0;
}
这里的struct Stu是结构体关键字加结构体标签,他们加起来就是结构体类型,我们创建一个变量int a=0;这里的int类型和结构体类型相似 所以结构体类型后面也需要创建一个变量 ,我们这里创建s
需要注意 struct Stu
{
char name[20];
short age;
char tele[12];
char sex[5];
};这个结构体是不占内存空间的,这部分代码只是来定义结构体类型,当我们真正创建参数时,例如main函数中的struct Stu s;才真正占用了空间,可以类比盖楼,图纸就等价于我们这一串代码,只是为了设定,并不等同与真正的施工。
这里的s为局部的结构体变量
struct Stu
{
char name[20];
short age;
char tele[12];
char sex[5];
}s1, s2, s3;
我们也可以在结构体类型的定义的最后加入变量s1,s2,s3,这里的s1,s2,s3是结构体变量,但是他们是全局变量,尽量不要使用全局变量
typedef struct Stu
{
char name[20];
short age;
char tele[12];
char sex[5];
}Stu;
接下来,引进一个typedef,这里的意思是把struct Stu结构体类型更换名字为最下面的Stu
int main()
{
struct Stu s1;
Stu s2;
return 0;
}
如图所示,struct Stu表示结构体类型 第二行的Stu s2也表示结构体类型。
结构体初始化
如何对结构体进行初始化
int main()
{
struct Stu s1 = { "张三", 20, "15538113652", "男" };
Stu s2 = { "张三", 20, "15538113652", "男" };
return 0;
}
结构体初始化的形式是结构体类型+变量名={对应的成员变量中的定义}
结构体成员的类型
结构的成员可以是标量,数组,指针,甚至是其他结构体
struct S
{
int a;
char c;
char arr[20];
double d;
};
struct T
{
char ch[10];
struct S s;
char*pc;
};
int main()
{
char arr[] = "hello bit\n";
struct T t = { "hehe", { 100, 'w', "hello world", 3.14 }, arr };
printf("%s\n", t.ch);
printf("%s\n", t.s.arr);
printf("%lf\n", t.s.d);
printf("%s\n", t.pc);
return 0;
}
如图,我们创建了两个结构体,第一个结构体的成员变量的类型按顺序为整型a,字符c,数组arr,和浮点型d(能保留两位有效数字)
第二个结构体的成员变量类型按顺序为数组ch,结构体struct S s,char类型的指针
接下来我们对struct T t进行初始化,第一个数组对应的是字符串“hehe”,第二个成员变量对应的是struct S s;所以我们要在struct T t对struct S s进行初始化
char arr[] = "hello bit\n";这里的意思是创建一个数组,因为结构体struct T t需要char*的指针来初始化,所以我们创建一个数组,数组arr首元素的地址就可以当作char类型的指针
printf("%s\n", t.ch);%s表示我们打印的是字符串,t.ch对应的是struct T t中的“hehe”
printf("%s\n", t.s.arr);t.s.arr表示struct T t中的struct S s中的char arr[20];%s则表示打印的是字符串,打印结果为“hello world”
printf("%lf\n", t.s.d); t.s.d表示struct T t中的struct S s中的double d;%lf表示打印的是浮点型,打印结果为3.14
printf("%s\n", t.pc); t.pc表示struct T t中的char*pc;%s表示的打印的是字符串,打印结果为“hello wordl“
hehe
hello world
3.140000
hello bit
请按任意键继续. . .
结果如图所示
typedef struct Stu
{
char name[20];
short age;
char tele[12];
char sex[5];
}Stu;
void print1(Stu tmp)
{
printf("name:%s\n", tmp.name);
printf("age:%d\n", tmp.age);
printf("tele:%s\n", tmp.tele);
printf("sex:%s\n", tmp.sex);
}
int main()
{
Stu s = { "李四", 40, "15536984521", "男" };
print1(s);
return 0;
}
接下来,我们创建一个结构体,并将其打印出来,typedef函数表示把结构体类型更名为Stu,print1(s)表示我们创建的打印函数,我们把变量s进行传参,void print(Stu tmp)对函数进行定义,void表示我们构建的函数是没有返回值的,因为我们传递的参数的类型为Stu,所以我们要用Stu来接受,tmp为临时变量来接收变量s,在打印函数中我们用四组printf函数将四组成员变量全部打印出来,这是第一种打印方法
name:李四
age:40
tele:15536984521
sex:男
请按任意键继续. . .
如图,打印结果正确
还有另一种打印方案
typedef struct Stu
{
char name[20];
short age;
char tele[12];
char sex[5];
}Stu;
void print1(Stu* pc)
{
printf("name:%s\n", pc->name);
printf("age:%d\n", pc->age);
printf("tele:%s\n", pc->tele);
printf("sex:%s\n", pc->sex);
}
int main()
{
Stu s = { "李四", 40, "15536984521", "男" };
print1(&s);
return 0;
}
第二种方案和第一种很相似,不同的地方在于使用了指针,print1(&s);我们把变量s的地址传到函数内部,因为指针s的类型为Stu,所以我们s的类型为Stu*,我们用Stu*pc来接收指针s,使用指针之后的打印函数,我们要用pc->来打印,pc->的意识是指向,指针指向的即为地址,通过访问地址的方法直接打印成员变量。
name:李四
age:40
tele:15536984521
sex:男
请按任意键继续. . .
打印结果。
这两种方法那种更好? 答案是第二种:因为第一种传递参数时,我们传递的是一个结构体变量作为实际参数,我们在函数内部也要对实际参数进行临时拷贝,需要拷贝出完全相同的结构体,所以需要额外占用内存空间,倒置压栈,对计算机性能产生影响,并且,拷贝的过程也需要时间,所以综合考虑,应该采用传地址的方法
传地址的过程种,无非传递的只有四个字节(32位平台)或者八个字节(64位平台),我们所需要创建的空间非常小。