C语言基础|【C语言入门必看】结构体

结构体
本章浅入了解结构体,在后面的自定义类型进阶会重点讲这部分内容。

文章目录

  • 一、结构体类型的声明
  • 二、结构体初始化
  • 三、结构体成员访问
  • 四、结构体传参

一、结构体类型的声明 结构体:用于描述属性不止一个的复杂对象
结构体是一些值的集合,这些值成为成员变量,且结构的成员可以是不同类型变量。
我们已经学习过:intcharfloatdouble等单一变量类型,但这些只能描述单一属性,所以C语言创造了包含多种单一变量结构体,方便描述复杂对象。比如一本书有书名、作者、价格等属性。
结构体的声明语法:
struct tag//struct - 结构体关键字;tag - 结构体标签;struct tag - 结构体类型名 { member-list; //成员列表 }variable-list; //变量列表

int类型本身不占据空间,当用int类型创建int整型变量时才会在内存中开辟空间。
同理,struct tag结构体类型本身不占据空间,当用结构体类型创建结构体变量才会在内存中开辟空间
如要声明一个学生类型,它的成员变量包括:名字、年龄、性别、学号。
struct Stu { //成员变量 char name[20]; //名字 int age; //年龄 char sex[5]; //性别 char id[20]; //学号 };

当觉得上述struct Stu结构体类型名太长,这时候需要用到类型重定义typedef
typedef struct Stu { //成员变量 char name[20]; //名字 int age; //年龄 char sex[5]; //性别 char id[20]; //学号 }Stu;

【C语言基础|【C语言入门必看】结构体】这样,struct Stu就等效于Stu
结构体成员的类型:
结构的成员可以是标量、数组、指针,甚至是其他结构体(内嵌)。
二、结构体初始化 有了结构体类型,定义结构体变量就简单啦!
struct Stu { //成员变量 char name[20]; //名字 int age; //年龄 char sex[5]; //性别 char id[20]; //学号 }s1; //①声明类型的同时定义变量s1 struct Stu s2; //定义全局变量s2 int main() { struct Stu s3; //③定义局部变量s3 struct Stu s4 = { "张三",17,"男","20200360318" }; //④定义结构体变量s4的同时可初始化 return 0; }

以上是创建结构体变量的方式。当执行类型重定义typedef struct {...} Stu; 后代码中的struct Stu可替换成Stu
注:在main函数内创建的结构体变量是局部变量,在栈区开辟空间;在main函数外,则为全局变量,在静态区开辟空间。
结构体内可嵌套结构体:
struct S { int a; char c; double d; }; struct T { struct S s; char name[20]; int num; }; int main() { struct T t = { {100, 'w', 3.14}, "张三", 17 }; return 0; }

结构体变量t内含有用结构体类型S创建的s。在给s初始化时,得用{}
三、结构体成员访问
  1. . 操作符
    结构体变量成员可通过 . 操作符访问,它有两个操作数,左边为结构体变量名,右边为结构体成员变量名。
    借用上面结构体嵌套的例子:
    C语言基础|【C语言入门必看】结构体
    文章图片
st的成员变量,abcs的成员变量,访问abc则为t.s.at.s.bt.s.c
  1. -> 操作符
    结构体变量成员也可通过 -> 操作符访问,它有两个操作数,左边为结构体指针变量,右边为结构体成员变量。
struct T t = { {100, 'w', 3.14}, "张三", 17 }; struct T* pt = &t; //结构体指针变量pt //1.对结构体指针解引用找到指针所指向的结构体 printf("%d %c %lf %s %d\n", (*pt).s.a, (*pt).s.c, (*pt).s.d, (*pt).name, (*pt).num); //2.通过结构体指针直接获得成员变量 printf("%d %c %lf %s %d\n", pt->s.a, pt->s.c, pt->s.d, pt->name, pt->num);

四、结构体传参
#include struct S { int data[1000]; int num; }; //结构体类型的声明//结构体传参 void print1(struct S s) { printf("%d\n", s.num); } //结构体地址传参 void print2(struct S* ps) { printf("%d\n", ps->num); } int main() { struct S s = { {1,2,3,4}, 1000 }; print1(s); //传结构体 print2(&s); //传地址 return 0; }

上面的 print1print2 函数哪个好些?
答案是:首选print2函数。
原因:
函数传参的时候,参数是需要压栈的。 如果传递一个结构体对象的时候,结构体过大,参数压栈的系统开销比较大,所以会导致性能的下降。
结论:
结构体传参的时候,建议传结构体的地址。

    推荐阅读