结构体

结构体

引入

存储数据: 变量(int a;)、数组(int a[10]),但是现实存储的对象比较复杂,比如:“狗”、“学生”,该怎么 存储到计算机中?使用对象的属性表示一个对象(名词):

学生的属性:

  1. 学号 => char num[12];

  2. 年龄 =>int

  3. 性别 => char Femal/Male

  4. 学制 = >int

  5. 姓名 => char name[30];

    =======> 就需要使用结构体,结构体可以存储多种 不同类型的数据。可以作为一个整体,表示一个对象。

    ======》允许自己定义组合数据类型

    ======》 结构体(struct)、共用体(union)、enum(枚举,属于整型)

结构体

定义类型

struct 结构体名字{
	成员类型1  成员变量名1;
	成员类型2  成员变量名2;
    ...
};
struct Birthday{
    
    int year;
    int month;
    int day;
};
//定义了自定义了struct Student这种类型
struct Student{
    char name[20];//
    int age;
    char sex;
    char no[20];
    struct Birthday day;//出生年月日
};

//1. 结构体名字: 合法的标识符即可,建议第一个字母大写
//2. 成员类型:合法数据类型即可(int char double char[] int* struct  struct Student* union enum)
//3.成员变量: 合法的标识符即可

定义变量

struct 结构体类型名 变量名;
struct Student  p;//struct Student是一种类型
				 //p是变量名

结构体变量的空间分配

  1. 按照定义的成员变量的顺序进行空间分配

  2. 结构体变量的空间分配是所有成员变量空间分配的总和,可能会因为字节对齐而产生一些填充

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9WCVwIob-1609289927731)(结构体笔记1.assets/image-20201229095957754.png)]

结构体变量的使用

赋值,实际上是对成员变量进行赋值
//结构体变量名.成员变量名
struct Student p;//p是结构体变量
p.age = 10;
printf("p.age: %d\n",p.age);//访问的时候只能输出成员变量
取值,实际上是把成员变量的值取出来输出
struct Student q;
q = p;//结构体变量之间是可以相互赋值 q.day == p.day!!!!
//注意:不能printf("?",p);不能整体进行输出
printf("p.age: %d\n",p.age);

结构体指针变量的访问

定义
//定义格式:struct 结构体名* 指针变量名;
struct Student* s;//s是一个指针变量名,指向的类型应该是struct Student
//1
struct Student p;//p是结构体变量
s = &p;
//2
s = (struct Student* )malloc(sizeof(struct Student));
//3
struct Student* q;
q = p;//p和q指向同一个空间

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PGr0HJFy-1609289927734)(结构体笔记1.assets/image-20201229105634106.png)]

赋值(通过结构体指针变量对成员变量赋值)
//使用s,对s指向的空间中(p)的成员变量(name,age)进行赋值
//定义格式: 结构体指针变量->成员变量
s->age = 10;
s->sex = 'f';
strcpy(s->name,"lisi");
取值(通过结构体指针变量把指向的空间的成员变量值取出来)
printf("%d",s->age);
printf("%s",s->name);

⚠️结构体变量 不能整体输入和输出,只能一个一个输入或者输出其成员变量

定义结构体数组

struct Student stu[5];//定义了5个结构体变量
//访问成员变量
stu[0]   stu[0].age
stu[1]   stu[1].age
    。。。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZqE4wqxo-1609289927736)(结构体笔记1.assets/image-20201229144752352.png)]

结构体变量的初始化

struct Student{
    char name[20];//
    int age;
};
  1. 按照定义的顺序进行初始化

    struct Student s = {"zhangsan",10};
    
  2. 不按照顺序进行初始化

    struct Student s = {
        .age = 10,
        .name = "zhangsan"
    };
    
  3. 结构体数组进行初始化

    1. 按顺序进行初始化
    struct Student stu[5] = {
        {
            "zzhangsan",10
        },//stu[0]
        {
            .age = 10,
            .name = "lisi" 
        }//stu[1]的值
    }
    

    b.不按照顺序初始化(不是所有的编译器支持)

    struct Student stu[5] = {
    [1] = {
         "zzhangsan",10
     },//stu[1]
    [2] =  {
         .age = 10,
         .name = "lisi" 
     }//stu[2]的值
    }
    

结构体中字节对齐

  1. 结构体内部的成员变量需要在指定的起始地址上进行存储,跟系统的位数相关(32 64 )

  2. 结构体存储的时候会指定起始的地址,即结构最终的字节数按照最大宽度进行字节对齐

    最大宽度:成员变量中 字节对齐的值 最大的

32位:

​ char 1字节对齐,要求存储的地址1的整数倍

​ short 2字节对齐,要求存储的地址2的整数倍

​ int 、long 、float 、指针变量 4字节对齐,要求存储的地址4的整数倍

double Windows 8字节对齐,Linux上是4字节对齐

struct MixData{
  char d1;// 0 -- 1
  short d2;//2  ---> 2  
}
sizeof(struct MixData) <=====> 4 

​ [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y3xKXiHm-1609289927738)(结构体笔记1.assets/image-20201229154850450.png)]

struct MixData{
    char d1;// 0
    int d2;//4 5 6 7 
    char d3//8  
};//9 个,最大宽度:4
//的大小是最大宽度的整数倍 ---> 12
sizeof(struct MixData)<==============> 12

64位系统:

​ char 1字节对齐,要求存储的地址1的整数倍

​ short 2字节对齐,要求存储的地址2的整数倍

​ int 、float 、指针变量 4字节对齐,要求存储的地址4的整数倍

long doouble 8字节对齐,要求存储地址8的整数倍

struct MixData{
    char a1;// 0 
    char a2;//1
    int a3;//4 5 6 7 
};
sizeof(struct MixData) <=====> 8
struct MixData{
    char a1;//0 
    int a3;//4 5 6 7 
    char a2;//8 
};//9 整体对齐: 最大的宽度 4   ===
sizeof(struct MixData) <=====> 12
struct MixData{
    int a3;//0 1 2 3
    char a1; //4
    char a2;//5
};
sizeof(struct MixData) <=====> 8
struct MixData{
    char a1;//0 
    double a3;//8 9 10 11 12.. 15 
    char a2;//16
};//17 ---> 最大宽度(8)
sizeof(struct MixData) <=====>  24 

练习

  1. 定义struct Student 结构体变量,对齐进行赋值和输出

  2. 输入5个结构体变量,按照年龄大小进行排序输出+

    struct Student{
        char name[20];//
        int age;
    };
    //1.输入 【结构体数组】
    	
    //2.排序
    
    //3.输出【使用指针变量的形式】
    	p = &stu[0];//通过p输出其成员变量
    
    1. 结构体数组输入与输出\

      //1.输入
      struct Student s[5];//s[0] s[1]
      	int i = 0;
      	for(i = 0; i < 5; i++){
      		scanf("%s %d",s[i].name,&s[i].age);
      	
      	}
      	for(i = 0; i < 5; i++){
      		printf("%s %d\n",s[i].name,s[i].age);
      	}
      
      

    ​ b.结构体数组输入与输出

    //2. 输入与输出
    	struct Student* stu;//stu中存储的是随机值,指向的空间随机
    	for(int i = 0; i < 5; i++){	
    		stu = &s[i];//&(s[0])  &s[1]  (s + i)
    		scanf("%s %d",stu->name,&stu->age);
    	}
    	                                                     
    	//2.排序
    	//3.输出
    	for(int i = 0; i < 5; i++){
    		stu = (s + i);
    		printf("%s %d\n",stu->name,stu->age);
    		//printf("%s %d",(*stu).name,(*stu).age);
    	}
    	
    
  3. 结构体的大小

    struct FinalPad{
        
      float x;//4    0 1 2 3
      char n[1];//1  4 
    };//5 ---> 整个结构字节对齐: 8
    sizeof(struct FinalPad) === 
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值