C语言——结构体 (C语言入门结束~ 以后更新进阶C )

@[toc]数组

1.结构体类型的声明

结构体的基础知识:markdown

结构体是一些值的集合,这些值称为成员变量。
结构体的每一个成员能够是不一样类型的变量。ide

结构体的由来 / 意义 / 做用:函数

现实生活中,咱们会遇到不少复杂的对象,这些复杂的对象仅经过c语言中的整型数据类型或者浮点数数据类型是没法全面且准确的描述的,这时候咱们就须要用结构体来描述这些复杂的对象性能

结构体的声明:学习

struct tag  //struct---结构体关键字  tag---结构体标签   struct tag---结构体类型
{
    member - list;   //结构体成员列表
}variable - list;    //结构体变量列表

例如描述一个学生:3d

#include<stdio.h>

//描述一个学生---一些数据
//名字、年龄、电话、性别
//struct---结构体关键字  Stu---结构体标签  struct Stu---结构体类型

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;
}

结构体类型至关于 int 自己不占据空间,只有当用结构体类型建立结构体变量的时候(利用int建立整型变量)才占据内存空间。指针

举例 中结构体类型是 struct Stu,若是咱们嫌弃这个名字太长了,能够对其进行一个类型重定义,使用类型重定义关键字 typedef 将struct Stu 重定义成 Stu;重定义类型名称后,结构体变量的建立仅需使用Stu,如图:code

image-20210807135915584

结构体成员的类型: 结构体成员能够是变量、数组、指针、甚至是其它结构体。对象


2.结构体变量的定义和初始化

①建立结构体类型的同时定义结构体变量

struct Point
{
    int x;
    int y;
}p1;//声明类型的同时定义变量p1

②先建立结构体类型,再定义结构体变量

struct Point p2;  //先建立结构体类型,再定义结构体变量

③初始化:定义变量的同时赋初值

// 初始化例如:
 struct Point p3 = { 1,1 };
 Stu s = { " 潘 ",20,"11011912011","男" };

结构体里包含结构体初始化:

#include<stdio.h>
struct S
{
    int a;
    char c;
    char arr[20];
    double d;
};

struct T
{
    char ch[10];
    struct S s;
    char* pc;
};

int main()
{
    int arr[]={1,2,3,4,5,6,7,8,9}
    //建立一个struct T 类型的结构体变量
    //初始化的时候,成员若是是结构体,须要用{ }括起来。

    struct T t = { "hello",{100, 'w' ,"hello world",3.14}, arr };
    //指针不知道赋什么值的时候,能够赋NULL
    //先用t.s 找到结构体类型成员 再用 .去访问结构体成员里面的成员 t.s.arr

    printf("%s\n", t.ch);     //打印 hello
    printf("%s\n", t.s.arr);  //打印 hello world
    printf("%lf\n",t.s.d);    //打印 3.14
    printf("%p\n", t.pc);     //打印 arr[]指针
    printf("%d\n", t.pc);     //打印 arr的值

    return 0;
}

3.结构体成员的访问

结构体变量访问成员结构变量的成员是经过点操做符( . )访问的。点操做符接收两个操做数。

image-20210807141819250

②结构体指针访问指向变量的成员有时候咱们获得的不是一个结构体变量,而是指向一个结构体的指针。

image-20210807141923733

再例如:

struct Stu
{
char name[20];
int age;
};

void print(struct Stu* ps)
{
printf("name = %s   age = %d\n", (*ps).name, (*ps).age);    //使用结构体指针访问指向对象的成员
printf("name = %s   age = %d\n", ps->name, ps->age);
}

int main()
{
   struct Stu s = {"zhangsan", 20};
   print(&s);//结构体地址传参
   return 0;
}

4.结构体传参

#include<stdio.h>

typedef struct Stu
{
    //成员变量
    char name[20];
    short age;
    char tele[12];
    char sex[5];
}Stu;

void Print1(Stu s)
{
    printf("name:  %s\n", s.name);
    printf("age:   %d\n", s.age);
    printf("tele:  %s\n", s.tele);
    printf("sex:   %s\n", s.sex);
}

void Print2(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;//建立结构体变量,局部结构体变量
    Stu s = { "张同窗",20,"11011912011","保密" };
    Print1(s);
    Print2(&s);
    return 0;
}

image-20210807142806823


上面的 print1 和 print2 函数哪一个好些?

答案是:首选 print2 函数。

image-20210807143710865

缘由:函数传参的时候,参数是须要压栈的。 若是传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,因此会致使性能的降低。

结论:结构体传参的时候,要传结构体的地址。


拓展:

这里咱们说到了一个概念:压栈

以前的学习知道了,程序内存主要分为三个区域,栈区、堆区、静态区

栈区:局部变量、函数的形式参数、函数调用也开辟空间
堆区:动态内存分配、malloc / free、realloc、calloc
静态区:全局变量、静态变量

画图理解:

无标题

栈:

①插入一个元素-- - 压栈
② 删除一个元素-- - 出栈

栈的特色:先进后出,后进先出。

image-20210807145126088

相关文章
相关标签/搜索