结构体的使用

一、为什么要有结构体?

        在c语言中提供了很多的数据内省如char、int、float、long、double等等,这些为基本的数据内型,可以定义单个变量。当然我们定义变量可以有几个变量就定义几个变量,有很多意义相关的变量可以用数组来定义,但是碰见了意义相关但数据类型不一样的时候数组就派不上用场了,因为一个数组只能存储类型相关的变量,这个时候也就产生了结构体。

        什么是结构体呢?结构体是一种里面包含很多元素、这些元素的数据类型可以是相同、也可以是不同,所以结构体是一种数据封装的方法。

二、如何声明结构体?

        要想声明一个结构体,就得用到一个关键字struct,结构体的声明格式如下:

Struct 结构体名{
成员列表;
}变量名列表;

注:结构体名一般都为大写,方便与变量区分开。成员列表以及变量名列表可以是一个也可以是多个。

其实结构体的定义归根结底也就三种,关于结构体声明的三种方法,这里我以日期作为例子:

2.1 结构体声明用法一:单独定义

struct Data
{
    uint16_t  Year;
    uint8_t  Mon;
    uint8_t Day;
};
 
int main()
{
    struct Data Today;
    struct Data Tomorrow;
    Today.Year = 2024;
    Today.Mon  = 5;
    Today.Day  = 24; 
    Tomorrow.Day = 25;
    printf("Today Data:%d-%d-%d\n",Today.Year,Today.Mon,Today.Day);
    printf("Tomorrow Data:%d-%d-%d\n",Today.Year,Today.Mon,Tomorrow.Day);
}

当然创建变量部分可以放在函数体也可以放在函数外,无非是局部变量与全局变量。

2.2 结构体声明用法二:混合定义

struct Data
{
    uint16_t  Year;
    uint8_t  Mon;
    uint16_t Day;
}Today;
 
int main()
{
    Today.Year = 2024;
    Today.Mon  = 5;
    Today.Day  = 24; 
    printf("Today Data:%d-%d-%d\n",Today.Year,Today.Mon,Today.Day);
}

        这里我们声明了一个结构体,其名字为Data,成员有年、月、日,变量名为今天。(当然你还可以加上明天,在变量名后加逗号分隔,写上Tomorrow)。如:

struct Data
{
    uint16_t  Year;
    uint8_t  Mon;
    uint16_t Day;
}Today,Tomorrow;
 
int main()
{
    Today.Year = 2024;
    Today.Mon  = 5;
    Today.Day  = 24; 
    Tomorrow.Day = 25;
    printf("Today Data:%d-%d-%d\n",Today.Year,Today.Mon,Today.Day);
    printf("Tomorrow Data:%d-%d-%d\n",Today.Year,Today.Mon,Tomorrow.Day);
}

这里我省了明天的年月赋值,直接用的是Today的。

2.3 结构体声明用法三:匿名结构体

struct 
{
    uint16_t  Year;
    uint8_t  Mon;
    uint8_t Day;
}Today,Tomorrow;
 
int main()
{
    Today.Year = 2024;
    Today.Mon  = 5;
    Today.Day  = 24; 
    Tomorrow.Day = 25;
    printf("Today Data:%d-%d-%d\n",Today.Year,Today.Mon,Today.Day);
    printf("Tomorrow Data:%d-%d-%d\n",Today.Year,Today.Mon,Tomorrow.Day);
}

这种结构体的定义只能使用一次,也就是你开局就确定了结构体变量,因为你省去了结构体名,也就是你无法再通过struct再定义一个结构体变量。

三、typedef与结构体

        当我们使用法一去定义结构体以及变量的时候,都需要加上struct关键字,要想在定义结构体变量省去struct关键字,我们就可以在声明结构体时加上关键字typedef。

        在之前我们先了解一下关键字typedef的作用,它可以给变量类型换名字,例如下列代码,通过typedef给类型起别名,也就是下边的Data 就相当于上边srtuct Data。当然struct后的Data结构体名可以省去,这也就是为什么下边声明结构体变量时不需要加struct的原因,Data中已经包含struct了。这也就导致了为什么有些结构体花括号外面有时为结构体变量,有时候有为名字,以至于很多人懵懵懂懂,现在大家知道了结构体该如何定义了吧!

typedef struct Data
{
    uint16_t  Year;
    uint8_t  Mon;
    uint8_t Day;
}Data;
 
int main()
{
    Data Today;
    Data Tomorrow;
    Today.Year = 2024;
    Today.Mon  = 5;
    Today.Day  = 24; 
    Tomorrow.Day = 25;
    printf("Today Data:%d-%d-%d\n",Today.Year,Today.Mon,Today.Day);
    printf("Tomorrow Data:%d-%d-%d\n",Today.Year,Today.Mon,Tomorrow.Day);
}

四、结构体的嵌套

struct Time{
    uint8_t hour;
    uint8_t minute;
    uint8_t second;
};

typedef struct
{
    uint16_t  Year;
    uint8_t  Mon;
    uint8_t Day;
    struct Time time;
    
}Data;

        这样就完成了结构体的嵌套,当然这两个完全可以拿一个结构体全部定义完成,我这里只是举例子,定义了一个结构体其中包含另一个结构体,其中为时分秒。

五、结构体的赋值

        上面讲了结构体的定义,那么该如何赋值呢?方法1是直接引出结构体变量进行一个个赋值:

    Data Today;
    Today.Year = 2024;
    Today.Mon  = 5;
    Today.Day  = 24; 
    Today.time.hour = 12;
    Today.time.minute = 45;
    Today.time.second = 55;

第二种方法是利用大括号进行赋值:注“嵌套的结构体赋值还得加上大括号”

struct Time{
    uint8_t hour;
    uint8_t minute;
    uint8_t second;
};

typedef struct
{
    uint16_t  Year;
    uint8_t  Mon;
    uint8_t Day;
    struct Time time;
}Data;
 
int main()
{
    Data Today = {2024,5,24,{12,45,55} };
    printf("Today Data:%d-%d-%d %d:%d:%d\n",Today.Year,Today.Mon,Today.Day,
                    Today.time.hour,Today.time.minute,Today.time.second);
}

六、结构体数组

6.1 结构体数组的作用

        结构体数组是c语言中处理复杂数据的一种强大工具,通过结构体数组,我们可以操作管理多个相同类型的结构体数据。结构体数组是一种特殊的数组,他每个元素都是一个结构体。通过结构体数组,我们可以将多个相关联的结构体数据组织在一起,形成一个逻辑单元。

 6.2结构体的使用

        关于结构体的定义声明和上边讲的结构体定义方法一样,也是三种,这里直接使用第二种,还是拿日期举例子:

struct Data
{
    uint16_t  Year;
    uint8_t  Mon;
    uint16_t Day;
}Dat[3]={{2025,1,1},{2025,1,2},{2025,1,3}};
 
int main()
{
    printf("Today Data:%d-%d-%d\n",Dat[0].Year,Dat[0].Mon,Dat[0].Day);
    printf("Tomorrow Data:%d-%d-%d\n",Dat[1].Year,Dat[1].Mon,Dat[1].Day);
    printf("The day after tomorrow Data:%d-%d-%d\n",Dat[2].Year,Dat[2].Mon,Dat[2].Day);
}

七、结构体指针

       通过指向结构体变量的指针变量输出结构体变量中成员的信息。

struct student
{
    char name[4];
    char age;
}*P;
 
//或者写成
struct student
{
    char name[4];
    char age;
};
 
student *p;

如何使用指针访问结构体成员呢?

        方法一:        (*p).name = "ABC";

        方法二:        p->name = "ABC";

八、结构体的内存计算

struct Time{
    uint8_t hour;
    uint8_t minute;
    uint8_t second;
};

typedef struct
{
    uint16_t  Year;
    uint8_t  Mon;
    uint8_t Day;
    struct Time time;
}Data;
 
int main()
{
    Data Today;
    printf("Time Size:%d\n",sizeof(Today.time));
    printf("Time Size:%d\n",sizeof(Today));
}

假如上述两个结构体,它们分别占多少字节呢?对于第一个结构体,里面有三个无符号字符型成员,也就是3字节,对于第二个结构体,4+1+1+3=9字节,那么结果是不是这样呢?我们试着打印出来:

                                   

        可以发现第一个结构体确实是三字节,但是第二个结构体就不一样了,占12字节。这里涉及到了另一个知识就是内存对齐,也就是第二个结构体其第一个变量占四个字节,而后边会自动将两个字节的char算成4字节,再把三字节的结构体也算成四字节,也就是有三个四字节所以为12。

        我们再在这个结构体里面添加成员:

typedef struct
{
    uint8_t  Mon;
    uint16_t  Year;
    uint8_t Day;
    uint16_t  Year2;
    uint8_t Day2;
    uint16_t  Year3;
    uint8_t Day3;
    struct Time time;
}Data;

         我们来计算一下内存,其中mon和day为一字节,一起为两字节,中间有4字节的year,也就是这三个一起占两个四字节也就是八字节,year2和day2都是四字节(内存对齐使day2为四字节),同理,也就是有4+4+4+4+4+4+4=28字节,可以发现确实没问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值