一、结构体的基础知识
结构体是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。
1.结构的声明
struct tag
{
member-list;
} variable-list;
创建结构体变量的具体举例:
//定义一个结构体
//struct--结构体关键字 Stu--结构体标签 struct Stu--结构体类型
struct Stu
{
//成员变量
char name[20];
short age;
char tele[12];
char sex[5];
};
int main()
{
struct Stu s; //创建结构体变量
return 0;
}
也可以在定义结构体时在其后创建全局的结构体变量。
struct Stu
{
//成员变量
char name[20];
short age;
char tele[12];
char sex[5];
}s1,s2,s3; //s1,s2,s3是三个全局的结构体变量
int main()
{
struct Stu s; //局部的结构体变量
return 0;
}
也可以采用typedef重命名,然后进行创建,比较简便。
typedef struct Stu
{
//成员变量
char name[20];
short age;
char tele[12];
char sex[5];
}Stu;
int main()
{
struct Stu s1;
Stu s2;
return 0;
}
2.结构成员的类型
结构的成员可以是变量、数组、指针,甚至是其他结构体。
二、结构体变量的定义和初始化
简单的初始化举例如下:
typedef struct Stu
{
//成员变量
char name[20];
short age;
char tele[12];
char sex[5];
}Stu;
int main()
{
struct Stu s1 = {"张三",20,"12332112345","男"};
Stu s2 = {"李四",30,"11451488888","女"};
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 world\n"
struct T t = {"hehe",{100,'w',"hello world",3.14},arr};
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 world\n"
struct T t = {"hehe",{100,'w',"hello world",3.14},arr};
printf("%s\n",t.ch); //hehe
printf("%s\n",t.s.arr); //hello world
printf("%lf\n",t.s.d); //3.14
printf("%s\n",t.pc); //helo world
return 0;
}
除此之位,当我们得到了一个结构体的指针,我们也可以通过指针来访问结构成员。
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);
}
void Print1(Stu* ps)
{
printf("name: %s\n",ps->name);
printf("age: %d\n",ps->age);
printf("tele: %s\n",ps->tele);
printf("sex: %s\n",ps->sex);
}
int main()
{
struct Stu s = {"张三",20,"12332112345","男"};
Print1(s); //传结构体
Print2(&s); //传地址
return 0;
}
对于上述两种传参方法,地址传参相对于传结构体要更加优越。因为函数传参时,参数需要压栈,如果传递一个结构体对象时,结构体过大,参数压栈的系统开销就会变大,导致性能下降。
小拓展
内存分为三个区域:栈区、堆区、静态区,它们会分别储存不同的东西。 栈区储存局部变量、函数的形式参数、函数调用需要开辟的空间;堆区储存动态开辟的内存(如malloc/free、realloc、calloc);静态区储存全局变量、static修饰的变量。
对于一个程序:
int Add(int x,int y)
{
int z = 0;
z = x + y;
return z;
}
int main()
{
int a = 10;
int b = 20;
int ret = 0;
ret = Add(a,b);
return 0;
}
Ⅰ 执行时会先开辟一块空间给main函数,然后在这片空间内先分配一片空间给变量a,再分配一片区域给变量b,然后是ret;
Ⅱ 紧接着调用函数所用的形参从后往前储存,先开辟空间给形参y,再开辟区域给形参x;
Ⅲ 然后开辟区域给Add函数,再这片空间给变量z分配空间,然后调用x,在调用y。
这里不得不提到数据结构的相关知识,数据结构分为线性数据结构(顺序表、链表、栈、队列等),树形数据结构(二叉树等),图等。【水平有限,为了学会了再详细展开说说】
对于顺序表,就是数据连续存储;
链表,就是一串分开储存的数据串联在一起;
栈,则是满足先进的后出,后进的先出(像堆了一层书,取用时最后放也就是最上层的要先被拿走)。插入一个元素叫做压栈,删除一个元素则叫做出栈。
本文为学习C语言心得与笔记记录,部分举例来源于B站C语言教学up主鹏哥