数据结构中结构体和共用体的学习

本文详细介绍了C语言中结构体的定义、初始化方式,包括直接定义、间接定义、结构体数组以及结构体指针的使用。同时提到了结构体嵌套结构体和共用体的概念,包括共用体的初始化和在结构体内外的使用情况。此外,还讨论了结构体的字节对齐原则和内存布局。
摘要由CSDN通过智能技术生成

结构体

结构体:存储类型相同或者不同的构造类型

//格式:
    struct 结构体名
    {
        数据类型 成员1;
        数据类型 成员2;
        数据类型 成员3;
        ...
        数据类型 成员n;
    };

struct:结构体关键字;
结构体名:需要满足命名规范,可有可无。和typedef结合,直接定义结构体变量
{}不可以省略
成员变量的数据类型:基本类型,构造类型,指针,空类型
成员的个数任意
结构体描述计算机不分配空间,直到定义结构体变量
结构体字节大小,是各个成员字节的总和

  • 定义车的信息:品牌,单价,颜色,车牌号
    struct Car
    {
        char name[20];    //品牌
        int price;        //单价
        char color[10]    //颜色
        char id[20]        //车牌号
    };
    struct Car//结构体自定义类型
    struct Car a;
    struct Car arr[3]
    struct Car *p;

基本结构体变量

间接定义结构体变量【常用】

间接定义:在定义结构体描述后,通过自定义结构类型定义变量

  • 间接定义变量按顺序初始化
    struct Car
    {
        char name[20];    //品牌
        int price;        //单价
        char color[10]    //颜色
        char id[20]        //车牌号
    };
    struct Car car={"大众",123456,"白色"};
    car.name
  • 间接定义变量不按顺序初始化
      struct Car
    {
        char name[20];    //品牌
        int price;        //单价
        char color[10]    //颜色
        char id[20]        //车牌号
    };
    struct Car car={.price=123456,.color="白色",.id="沪A1111"};
  • 间接定义变量,单个赋值
    struct Car
    {
        char name[20];    //品牌
        int price;        //单价
        char color[10]    //颜色
        char id[20]        //车牌号
    };
    struct Car car;
    strcpy(car.name,"大众");
    car.price=123456;
    strcpy(car.color,"白色");
    strcpy(car.id,"沪A88888");
  • 间接定义变量,输入赋值
        struct Car
    {
        char name[20];    //品牌
        int price;        //单价
        char color[10]    //颜色
        char id[20]        //车牌号
    };
    struct Car car;
    scanf("%s",car.name);
    scanf("%d",&car.price);
    scanf("%s",car.color);
    scanf("%s",car.id);

直接定义结构体变量

定义结构体描述的同时定义结构体变量

  • 直接定义变量按顺序初始化
    struct Car
    {
        char name[20];    //品牌
        int price;        //单价
        char color[10]    //颜色
        char id[20]        //车牌号
    }car={"大众",123456,"白色","沪A1111"};
  • 直接定义变量不按顺序初始化
      struct Car
    {
        char name[20];    //品牌
        int price;        //单价
        char color[10]    //颜色
        char id[20]        //车牌号
    }car={.price=123456,.color="白色",.id="沪A1111",.name="大众"};
  • 直接定义变量,单个赋值
    struct Car
    {
        char name[20];    //品牌
        int price;        //单价
        char color[10]    //颜色
        char id[20]        //车牌号
    }car;
    strcpy(car.name,"大众");
    car.price=123456;
    strcpy(car.color,"白色");
    strcpy(car.id,"沪A88888");
  • 直接定义变量,输入赋值
        struct Car
    {
        char name[20];    //品牌
        int price;        //单价
        char color[10]    //颜色
        char id[20]        //车牌号
    }car;
    scanf("%s",car.name);
    scanf("%d",&car.price);
    scanf("%s",car.color);
    scanf("%s",car.id);
  • 只有直接定义可以省略结构体名,无结构体名
    struct 
    {
        char name[20];    //品牌
        int price;        //单价
        char color[10]    //颜色
        char id[20]        //车牌号
    }car;

结构体数组

间接定义结构体数组并初始化

  • 间接定义变量按顺序初始化
    struct Car
    {
        char name[20];    //品牌
        int price;        //单价
        char color[10]    //颜色
        char id[20]        //车牌号
    };
    struct Car car[3]={"大众",123456,"白色","沪A1111",
                        "大众",123456,"白色","沪A2222",
                        "大众",123456,"白色","沪A33333"};
  • 间接定义变量不按顺序初始化
      struct Car
    {
        char name[20];    //品牌
        int price;        //单价
        char color[10]    //颜色
        char id[20]        //车牌号
    };
    struct Car car[3]={[0]={.price=123456,.color="白色",.id="沪A1111",.name="大众"},
                       [2]={.price=123456,.color="白色",.id="沪A2222",.name="大众"},
                        [1]={.price=123456,.color="白色",.id="沪A3333",.name="大众"}};
  • 间接定义变量,单个赋值
   struct Car
    {
        char name[20];    //品牌
        int price;        //单价
        char color[10]    //颜色
        char id[20]        //车牌号
    };
    struct Car car[3];
    car[0]:第一辆车的所有信息
    car[0].name:第一辆车的品牌
    car[2].id
    
    strcpy(car[0].name,"大众");
    car[0].price=123456;
    strcpy(car[0].color,"白色");
    strcpy(car[0].id,"沪A88888");
    
       strcpy(car[1].name,"大众");
    car[1].price=123456;
    strcpy(car[1].color,"白色");
    strcpy(car[1].id,"沪A88888");
    
       strcpy(car[2].name,"大众");
    car[2].price=123456;
    strcpy(car[2].color,"白色");
    strcpy(car[2].id,"沪A88888");
  • 直接定义变量,输入赋值
       struct Car
    {
        char name[20];    //品牌
        int price;        //单价
        char color[10]    //颜色
        char id[20]        //车牌号
    };
    struct Car car[3];
    for(int i=0;i<3;i++)
    {
        scanf("%s",car[i].name);
        scanf("%d",&car[i].price);
        scanf("%s",car[i].color);
        scanf("%s",car[i].id);
    }

直接定义结构数组并初始化

  • 直接定义变量按顺序初始化
    struct Car
    {
        char name[20];    //品牌
        int price;        //单价
        char color[10]    //颜色
        char id[20]        //车牌号
    } car[3]={"大众",123456,"白色","沪A1111",
                        "大众",123456,"白色","沪A2222",
                        "大众",123456,"白色","沪A33333"};
  • 直接定义变量不按顺序初始化
      struct Car
    {
        char name[20];    //品牌
        int price;        //单价
        char color[10]    //颜色
        char id[20]        //车牌号
    }car[3]={[0]={.price=123456,.color="白色",.id="沪A1111",.name="大众"},
                       [2]={.price=123456,.color="白色",.id="沪A2222",.name="大众"},
                        [1]={.price=123456,.color="白色",.id="沪A3333",.name="大众"}};
  • 直接定义变量,单个赋值
   struct Car
    {
        char name[20];    //品牌
        int price;        //单价
        char color[10]    //颜色
        char id[20]        //车牌号
    }car[3];
    car[0]:第一辆车的所有信息
    car[0].name:第一辆车的品牌
    car[2].id
    
    strcpy(car[0].name,"大众");
    car[0].price=123456;
    strcpy(car[0].color,"白色");
    strcpy(car[0].id,"沪A88888");
    
       strcpy(car[1].name,"大众");
    car[1].price=123456;
    strcpy(car[1].color,"白色");
    strcpy(car[1].id,"沪A88888");
    
       strcpy(car[2].name,"大众");
    car[2].price=123456;
    strcpy(car[2].color,"白色");
    strcpy(car[2].id,"沪A88888");
  • 直接定义变量,输入赋值
      struct Car
    {
        char name[20];    //品牌
        int price;        //单价
        char color[10]    //颜色
        char id[20]        //车牌号
    }car[3];
    for(int i=0;i<3;i++)
    {
        scanf("%s",car[i].name);
        scanf("%d",&car[i].price);
        scanf("%s",car[i].color);
        scanf("%s",car[i].id);
    }

结构体指针

格式:struct 结构体名 *指针变量名

  • 结构体指针指向普通结构体变量的地址
        struct Car
    {
        char name[20];    //品牌
        int price;        //单价
        char color[10]    //颜色
        char id[20]        //车牌号
    };
    struct Car c={.price=123456,.color="白色",.id="沪A1111",.name="大众"};
    struct Car *p=&c;
  • 结构体指针指向结构体数组的地址
   struct Car
    {
        char name[20];    //品牌
        int price;        //单价
        char color[10]    //颜色
        char id[20]        //车牌号
    };
    struct Car  car[3]={"大众",123456,"白色","沪A1111",
                        "大众",123456,"白色","沪A2222",
                        "大众",123456,"白色","沪A33333"};
    struct Car *p=car;
  • 结构体指针指向堆区空间的首地址
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
   struct Car
    {
        char name[20];    //品牌
        int price;        //单价
        char color[10];    //颜色
        char id[20]    ;    //车牌号
    };
//输出对去空间内存
void Output(struct Car *p,int len)
{

    for(int i=0;i<len;i++)
    {
    //    printf("%s\t%d\t%s\t%s\n",(p+i)->name,(p+i)->price,(p+i)->color,(p+i)->id);

    printf("%s\t%d\t%s\t%s\n",(*(p+i)).name,(*(p+i)).price,(*(p+i)).color,(*(p+i)).id);
    }
}
//在堆区空间申请
struct Car * create()
{
    
    struct Car *p=(struct Car *)malloc(sizeof(struct Car)*3);//
    if(NULL == p)
    {
    return NULL;
    }
    return p;

}
//在堆区实现循环输入
void Input(struct Car *p ,int n)
{

    for(int i=0;i<3;i++)
    {
    scanf("%s",(p+i)->name);
    scanf("%d",&(p+i)->price);//(p+i)->price===>price
    scanf("%s",(p+i)->color);
    scanf("%s",(p+i)->id);
    }

}
//释放堆区空间
struct Car * free_space(struct Car *p)
{
    if(NULL==p)
    {
    return NULL;
    }
    free(p);
p=NULL;
    return p;
}
int main(int argc, const char *argv[])
{

    struct Car  car[3]={"大众",123456,"白色","沪A1111",
                        "大众",123456,"白色","沪A2222",
                        "大众",123456,"白色","沪A33333"};
    struct Car *p=car;
    
    struct Car *p=create();

    Input(p,3);
    Output(p,3);
p=free_space(p);

    return 0;
}

结构体的引用

  • 普通结构使用各“.”进行引用;注意:只能使用结构体变量名引用
  • 结构体数组使用“.”进行引用,只能使用结构体数组名引用
  • 值使用“.”,地址使用“->”
  • 结构体名表示所有信息,不可以直接打印,结构体整体引用常用于传递参数,或者元素的赋值
   struct Car
    {
        char name[20];    //品牌
        int price;        //单价
        char color[10];    //颜色
        char id[20]    ;    //车牌号
    };
    struct Car a={"大众",123456,"白色","沪A1111"};
    struct Car b;
    printf("",b);
    //把a赋值给b
    strcpy(b.name,a.name);
    b.price=a.price;
    strcpy(b.color,a.color);
    strcpy(b.id,a.id);
    
    a:表示所有信息
    b=a;

typedef和结构体结合

 typedef struct  
    {
        char name[20];    //品牌
        int price;        //单价
        char color[10];    //颜色
        char id[20]    ;    //车牌号
    }car_t,car_arr[3],*car_p ;//a==》car_p 

car_t:不是变量名,是普通结构体类型别名
car_arr:不是结构体数组名,是结构体数组的别名
car_p:不是结构体指针变量名,是结构体指针的别名
当typedef和结构体结合时,结构体名可以省略不写

结构体嵌套结构体

  • 结构体嵌套普通结构
    定义一个学生:姓名、性别、出生日期【年月日】
 typedef struct
    {
        int year,month,day;
    }Birthday;
    typedef struct
    {
        char name[10];
        char sex;
        Birthday bir;
    }Stu;
    Stu student={"张三",'M',2000,7,14};
    printf("%s %c %d年%d月%d日\n",student.name,studnet.sex,student.bir.year,student.bir.month,student.bir.day);
  • 结构体嵌套结构体数组
    定义一个人的信息:姓名,性别,年龄,车辆多辆【品牌,单价】
 typedef struct
    {
        char name[10];
        int price;    
    }Car_t;
    typedef struct
    {
        char name[10];
        char sex;
        int age;
        Car_t arr[2]; 
    }person;
    person per={"张三",'M',18,"奔驰",555555,"宝马",666666};
    printf("",per.name,per.sex,per.age,per.arr[0].name,per.arr[0].price,per.arr[1].name,per.arr[1].price);

结构体字节计算

  • 结构体的总字节是各个成员字节的总和
  • 结构体变量的地址是第一个成员的地址,各个成员的地址连续
  • 结构体满足字节对齐原则
    i.结构体的首地址是最宽成员的倍数
    如果最宽成员是1字节,则地址是1的倍数
    如果最宽成员是2字节,则地址是2的倍数
    如果最宽成员是4字节,则地址是4的倍数
    如果最宽成员是8字节,则地址是8的倍数
    ii.结构体总字节数是最宽成员的倍数,如果不是则填充空字节
    iii.各个成员的地址偏移量是各个成员字节的倍数,如果不是则填充空字节
    地址偏移量:该成员的首地址到结构体的起始地址之间的差
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
    typedef struct
    {
    int a;
    float b;

    }A_t;
    A_t var;
    printf("&var=%p\t&var.a=%p\t&var.b=%p\n",&var,&var.a,&var.b);
    printf("sizeof(A_t)=%ld\n",sizeof(A_t));//8

    typedef struct{
    char a;
    double b;
    }B_t;
B_t var1;
    printf("&var1=%p\t&var1.a=%p\t&var1.b=%p\n",&var1,&var1.a,&var1.b);
    printf("sizeof(B_t)=%ld\n",sizeof(B_t));//16

    typedef struct
    {
    int a;
    char b;
    float c;
    char *p;
    char d;
    }C_t;
C_t c;
    printf("c.a=%p\n",&c.a);
    printf("c.b=%p\n",&c.b);
    printf("c.c=%p\n",&c.c);
    printf("c.p=%p\n",&c.p);
    printf("c.d=%p\n",&c.d);
    printf("sizeof(C_t)=%ld\n",sizeof(C_t));//32
    
    typedef char a_str[5];    
    typedef struct
    {
    a_str a;
    int b;
    }D_t;
    
    printf("sizeof(D_t)=%ld\n",sizeof(D_t));//12

    typedef struct{
    char a;
    double b;
    }E_t;
    typedef struct 
    {
    char a;
    short b;
    E_t c;
    }F_t;

    printf("sizeof(F_t)=%ld\n",sizeof(F_t));//24
    return 0;
}

32位操作系统

  • 结构体的总字节是各个成员字节的总和
  • 结构体变量的地址是第一个成员的地址,各个成员的地址连续
  • 结构体满足字节对齐原则
    i.结构体的首地址是最宽成员的倍数
    如果最宽成员是1字节,则地址是1的倍数
    如果最宽成员是2字节,则地址是2的倍数
    如果最宽成员是4字节或者8字节,则地址是4的倍数
    ii.结构体总字节数是最宽成员的倍数,如果不是则填充空字节
    如果最宽成员是4字节或者8字节,则总字节是4的倍数
    iii.各个成员的地址偏移量是各个成员字节的倍数,如果不是则填充空字节
    地址偏移量:该成员的首地址到结构体的起始地址之间的差
    如果最该成员是4字节或者8字节,则地址偏移量是4的倍数

共用体

共用体初始化

  • 默认为第一个元素赋值
typedef union 
    {
    int a;
    char b;
    double c;
    }A_t;
A_t var={97};//默认为第一个成员赋值
  • 指定某一个恒源赋值
 typedef union 
    {
    int a;
    char b;
    double c;
    }A_t;
A_t var1={.c=55.66};//指定为某一成员赋值

共用体和结构体结合

  • 共用体在结构体外
    typedef union
    {
        int a;
        double b;    
    }A_t;
    typedef struct
    {
        int a_v;
        A_t var;   
    }B_t;
    B_t a={100,20};//默认为共用体第一个成员a赋值
    B_t b={100,.var.b=55.66};//指定共用体成员b赋值
    a.a_v=100
    a.var.a=20
    
    b.a_v=100
    b.var.b=55.66
  • 共用体在结构体内
    typedef struct
    {
        int a_v;
        union 
        {
            int a;
            double b;    
        };
    }B_t;
    B_t b={100,.b=55.66};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值