C语言结构体、结构体数组、结构体指针学习整理

本文详细介绍了C语言中结构体的定义、初始化、变量赋值、数组操作、指针应用以及字节对齐规则,包括直接和间接定义结构体变量、结构体数组、结构体指针以及结构体在不同操作系统下的字节计算。示例代码涵盖了各种常见用法。
摘要由CSDN通过智能技术生成

一、结构体

格式:

struct 结构体名

{

        数据类型 成员1;

        数据类型 成员2;

        数据类型 成员3;

         ...

         数据类型 成员n;

};

格式解析:

1.struct:是结构体关键字

2.结构体名,需要满足命名规范,可以省略,与typedef结合直接定义结构体类型

3.{}不可以省略,;也不可省略

4.成员变量的数据类型可以为基本类型,构造类型,指针,空类型(void)

5.成员的个数任意

6.结构体描述时,计算机不分配空间,直到定义结构体变量计算机才分配空间,分配空间大小为各成员字节大小的总和

实例:

/*定义车的信息:品牌,单价,颜色,车牌号*/
struct Car
{
    char name[20];       //品牌
    int price;           //单价
    char color[10];      //颜色
    char id[20];         //车牌号
}; 

1.1 基本结构体变量

1.1.1 间接定义结构体变量及初始化

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

1)间接定义变量按顺序初始化

struct Car
    {
        char name[20];     //品牌
        int price;         //单价
        char color[10];    //颜色
        char id[20];       //车牌号
    };
struct Car car={"大众",123456,"白色","沪A1111"};

2)间接定义变量不按顺序初始化

struct Car
    {
        char name[20];      //品牌
        int price;          //单价
        char color[10];     //颜色
        char id[20];        //车牌号
    };
struct Car car={.price=123456,.color="白色",.id="沪A1111",.name="大众"};

3)间接定义变量,单个赋值

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");

注意:car.name="大众",这种赋值方式是错误的,在C99标准中不允许将字符串赋值给数组,如果强行赋值,编译器会直接报语法错误: [Error] assignment to expression with array type。

4)间接定义变量,输入赋值

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

1.1.2 直接定义结构体变量及初始化

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

1) 直接定义变量按顺序初始化   

 struct Car
    {
        char name[20];      //品牌
        int price;          //单价
        char color[10];     //颜色
        char id[20];        //车牌号
    }car={"大众",123456,"白色","沪A1111"};

2)直接定义变量不按顺序初始化     

 struct Car
    {
        char name[20];     //品牌
        int price;         //单价
        char color[10];    //颜色
        char id[20];       //车牌号
    }car={.price=123456,.color="白色",.id="沪A1111",.name="大众"};

3)直接定义变量,单个赋值 

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");

4)直接定义变量,输入赋值     

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

5) 直接定义可以省略结构体名,称“无名结构体” 

struct
    {
        char name[20];      //品牌
        int price;          //单价
        char color[10];     //颜色
        char id[20];        //车牌号
    }car;

1.2 结构体数组

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

1)间接定义变量按顺序初始化  

struct Car
    {
        char name[20];      //品牌
        int price;          //单价
        char color[10];     //颜色
        char id[20];        //车牌号
    };
struct Car car[3]={"大众",123456,"白色","沪A1111","大众",123456,"白色","沪A2222","大众",123456,"白色","沪A33333"};

2)间接定义变量不按顺序初始化

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="大众"}};

3)间接定义变量,单个赋值   

struct Car
    {
        char name[20];      //品牌
        int price;          //单价
        char color[10];     //颜色
        char id[20];        //车牌号
    };
struct Car car[3];
//第一辆车的信息
    strcpy(car[0].name,"大众");
    car[0].price=123456;
    strcpy(car[0].color,"白色");
    strcpy(car[0].id,"沪A1111");
//第二辆车的信息
    strcpy(car[1].name,"大众");
    car[1].price=123456;
    strcpy(car[1].color,"白色");
    strcpy(car[1].id,"沪A2222");
//第三辆车的信息
    strcpy(car[2].name,"大众");
    car[2].price=123456;
    strcpy(car[2].color,"白色");
    strcpy(car[2].id,"沪A3333");
    

4> 间接定义变量,输入赋值        

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

1.2.2 直接定义结构数组及初始化

1)直接定义变量按顺序初始化    

struct Car
    {
        char name[20];      //品牌
        int price;          //单价
        char color[10];     //颜色
        char id[20];        //车牌号
    }car[3]={"大众",123456,"白色","沪A1111","大众",123456,"白色","沪A2222","大众",123456,"白色","沪A33333"};

2)直接定义变量不按顺序初始化

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="大众"}};

3)直接定义变量,单个赋值   

 struct Car
    {
        char name[20];      //品牌
        int price;          //单价
        char color[10];     //颜色
        char id[20];        //车牌号
    }car[3];

    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");

4)直接定义变量,输入赋值

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

1.3 结构体指针

格式:

struct 结构体名 *指针变量名

1.3.1 结构体指针指向普通结构体变量的地址

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;

1.3.2 结构体指针指向结构体数组的地址

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;

1.3.3 结构体指针指向堆区空间的首地址

#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 *p=create();
    Input(p,3);
    Output(p,3);
    p=free_space(p);
    return 0;
}

1.4 结构体的引用

1.基本结构使用“.”进行引用,只能使用结构体变量名引用

2.结构体数组使用"."进行引用,只能使用结构体数组名引用

3.值使用".",地址使用“->”

4.结构体名表示所有信息,不可以直接打印,结构体整体引用常用于传递参数,或者元素的赋值   

struct Car
    {
        char name[20];     //品牌
        int price;         //单价
        char color[10];    //颜色
        char id[20];       //车牌号
    };
struct Car a={"大众",123456,"白色","沪A1111"};
struct Car b;
/*将a的赋值给b,方法一*/
    strcpy(b.name,a.name);
    b.price=a.price;
    strcpy(b.color,a.color);
    strcpy(b.id,a.id);
/*将a的赋值给b,方法一*/
    b=a;

1.5 typedef和结构体结合

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

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

1.6 结构体嵌套结构体

1.6.1 结构体嵌套普通结构

练习:定义一个学生:姓名、性别、出生日期【年月日】

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

1.6.2 结构体嵌套结构体数组

练习:定义一个人的信息:姓名,性别,年龄,车辆多辆【品牌,单价】

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

1.7 结构体字节计算

1.7.1 64位操作系统

1.结构体的总字节是各个成员字节的总和

2.结构体变量的地址是第一个成员的首地址,各个成员的地址连续

3.结构体需满足字节对齐原则

i.结构体的首地址是最宽成员的倍数

        如果最宽成员是1字节,则地址是1的倍数

        如果最宽成员是2字节,则地址是2的倍数

        如果最宽成员是4字节,则地址是4的倍数

        如果最宽成员是8字节,则地址是8的倍数

ii. 结构体总字节数是最宽成员的倍数,如果不是则填充空字节

iii.各个成员的地址偏移量是各个成员字节的倍数,如果不是则填充空字节

地址偏移量:该成员的首地址到结构体的起始地址之间的差

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

1.7.2 32位操作系统

1.结构体的总字节是各个成员字节的总和

2.结构体变量的地址是第一个成员的首地址,各个成员的地址连续

3.结构体需满足字节对齐原则

i.结构体的首地址是最宽成员的倍数

        如果最宽成员是1字节,则地址是1的倍数

        如果最宽成员是2字节,则地址是2的倍数

        如果最宽成员是4字节或者8字节,则地址是4的倍数

ii. 结构体总字节数是最宽成员的倍数,如果不是则填充空字节

        如果最宽成员是4字节或者8字节,则总字节是4的倍数

iii.各个成员的地址偏移量是各个成员字节的倍数,如果不是则填充空字节

        如果最该成员是4字节或者8字节,则地址偏移量是4的倍数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值