Bootstrap

结构体基本用法和字节对齐

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void test_struct_size();

/*结构体定义*/
struct grade
{
    int math;
    int english;
    float chinese;
};

/*结构体定义*/
struct student
{
    char name[16];
    int age;
    int class;
    int id;
    int score;
    char provience[16];
    /*结构体嵌套*/
    struct grade grade;
};

/*typedef简化定义,此处只是定义了类型,cla_1,cla_2*/
typedef struct class
{
    struct student stu[60];
    char teacher[60];
} cla_1,cla_2;

/*直接结构体声明全局变量*/
struct school
{
    cla_1 cla1_1[30];
    cla_2 cla2_2[30];
} sh;
/*直接定义结构体变量,不声明结构体类型*/
struct
{
   char subject[8];    
   int    score;
} test;

void main()
{
    printf("这是结构体基础知识练习\n");
    /*简化结构体,声明变量*/
    cla_1 class_1;
    cla_2 class_2;
    /*结构体初始化值的方式1*/
    struct student stu1 ={"XM",16,3,22,44,"CQ"};
    struct student stu2;
    strncpy(stu2.name, "XW",sizeof(stu2.name));
    stu2.age = 18;    
    stu2.class = 6;
    stu2.id = 16;
    strncpy(stu2.provience,"CD",sizeof(stu2.provience));
    printf("stu2.name:%s\n", stu2.name);
    
    /*结构体数组*/
    struct student stu[3];
    /*此处sizeof(数组名)就是数组所占空间的大小,sizeof(struct student)就是一个结构体的长度,注意记得加struct */
    for(int i=0;i<sizeof(stu)/sizeof(struct student);i++)    
    {
        printf("请输入第%d个学生的名字\n",i+1);
        scanf("%s",stu[i].name);
        printf("请输入第%d个学生的成绩\n",i+1);
        scanf("%d",&stu[i].score);
    }

    for(int i=0; i<sizeof(stu)/sizeof(struct student);i++)
    {
        printf("student[%d].name:%s;\nstudent[%d].sorce:%d\n\n",i+1,stu[i].name,i+1,stu[i].score);
    }


     /*结构体指针*/
    struct student *stu_point = NULL;
    /*结构体指针初始化,使用malloc方法*/
    stu_point =(struct student *)malloc(sizeof(struct student));
    strncpy(stu_point->name, "XK", sizeof(stu_point->name));
    stu_point->class = 100;
    stu_point->id = 90;
    printf("stu_point->name:%s\n",stu_point->name);
    printf("stu_point->class:%d\n",stu_point->class);
    printf("stu_point->id:%d\n",stu_point->id);
    if(stu_point)
        free(stu_point);

    /*结构体指针数组*/
    struct student *stu_point2[3];
    for(int i = 0; i<sizeof(stu_point2)/sizeof(struct student*);i++)
    {
        stu_point2[i] = (struct student*)malloc(sizeof(struct student));
        printf("请输入第%d个学生的名字\n",i+1);
        scanf("%s",stu_point2[i]->name);
        printf("请输入第%d个学生的成绩\n",i+1);
        scanf("%d",&stu_point2[i]->score);
    }    

    for(int i = 0; i<sizeof(stu_point2)/sizeof(struct student*);i++)
    {
        printf("学生:%s, 成绩:%d\n",stu_point2[i]->name, stu_point2[i]->score);
        if(stu_point2[i])
            free(stu_point2[i]);
    }

    test_struct_size();


}

/*
结构体字节对齐问题:
结构体计算大小由于要遵循计算机的访问规则,所以我们引入了内存对齐和偏移量的概念。

结构体内存对齐规则
1.第一个成员在结构体变量偏移量为0的地址处。
2.其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
对齐数 = 编译器默认的对齐数与该成员大小的较小值。
3.结构体总大小为最大对齐数的整数倍(每个成员变量都有一个对齐数)。
4.如果嵌套了结构体,嵌套的结构体对齐到自己最大对齐数的整数倍处,结构体的整体大小就是所有所有最大的对齐数的整数倍(包含嵌套结构体的对齐数)。
*/
struct s1
{
    char ch1;  //一个字节
    char ch2;   //一个字节 
    int ch3;   //四个字节,因此要遵循第一条规则,2个char一共偏移2个字节
};             //不是4的整数倍,因此要再多偏移两个字节,一共偏移8个字节

void test_struct_size()
{
    printf("siezof(struct s1)=%ld\n",sizeof(struct s1));/*输出的是8个字节*/
    printf("sizeof(struct class)=%ld\n", sizeof(struct class));
    printf("sizeof(cla_1)=%ld\n", sizeof(cla_1));
}

;