结构体

头文件

#include<stdio.h
#include<stddef.h

声明结构体

//声明一个学生类型,是想过学生类型来创建学生变量
//描述学生:属性-名字+电话+性别+年龄
struct Stu
{
    char name[20];
    char tele[12];
    char sex[20];
    int age;
}s4,s5,s6;

struct Stu s3;//全局变量

int main()
{
    //创建的结构体变量
    struct Stu s1;
    struct Stu s2;

    return 0;
}

匿名结构体类型

struct
{
    int a;
    char c;
}sa;

struct
{
    int a;
    char c;
}*psa;

int main()
{
    psa=&sa;//非法的

    return 0;
}

结构体的自引用

struct Node
{
    int date;
    struct Node* next;
};

int main()
{
    return 0;
}

typedef struct Node
{
    int date;//4
    struct Node* next;//4/8
}Node;

int main()
{
    struct Node n1;
    Node n2;

    return 0;
}

结构体的初始化

struct T
{
    double weight;
    short age;
};

struct S
{
    char c;
    struct T st;
    int a;
    double d;
    char arr[20];
};

int main()
{
    struct S s = {'c',{55.6,30},100,3.14,"hello bit"};
    printf("%c %lf %d %d %lf %s\n",s.c,s.st.weight,s.st.age,s.a,s.d,s.arr);

    return 0;
}

结构体内存对齐

struct S1
{
    char c1;
    int a;
    char c2;
};

struct S2
{
    char c1;
    char c2;
    int a;
};

struct S3
{
    double d;
    char c;
    int i;
};

struct S4
{
    char c1;
    struct S3 s3;
    double d;
};

int main()
{
    struct S1 s1 = {0};
    printf("%d\n",sizeof(s1));
    struct S2 s2 = {0};
    printf("%d\n",sizeof(s2));
    struct S3 s3 = {0};
    printf("%d\n",sizeof(s3));
    struct S4 s4 = {0};
    printf("%d\n",sizeof(s4));
    return 0;
}

#pragma pack(4)  //设置默认对齐数为4
struct S
{
    char c1;
    double d;
};
#pragma pack()  //取消默认对齐数

int main()
{
    struct S s;
    printf("%d\n",sizeof(s));
    return 0;

}

写一个宏,计算结构体中某变量相对于首地址的偏移 offsetof()宏的实现、

struct S
{
    char c;
    int i;
    double d;

};


int main()
{
    //offsetof();
    printf("%d\n",offsetof(struct S,c));
    printf("%d\n",offsetof(struct S,i));
    printf("%d\n",offsetof(struct S,d));
    return 0;
}

结构体传参

struct S
{
    int a;
    char c;
    double d;
};

void Init(struct S* ps)
{
    ps-a = 100;
    ps-c = 'w';
    ps-d = 3.14;
}
//传值
Print1(struct S tmp)
{
    printf("%d %c %lf\n",tmp.a,tmp.c,tmp.d);
}
//传址(推荐)
Print2(const struct S* ps)
{
    printf("%d %c %lf\n",ps-a,ps-c,ps-d);
}

int main()
{
    struct S s = {0};
    Init(&s);
    Print1(s);
    Print2(&s);
    /*s.a = 100;
    s.c = 'w';
    s.d = 3.14;

    printf("%d\n",s.a);*/
    return 0;
}

位段 - 二进制位 为了节省空间

struct S
{
    int a:2;
    int b:5;
    int c:10;
    int d:30;
    //后面数字不能大于32
};
//47bit - 6个字节*8 = 48bit
int main()
{
    struct S s;
    printf("%d\n",sizeof(s));//8个字节
    return 0;
}

位段的内存分配

```c
struct S
{
char a:3;
char b:4;
char c:5;
char d:4;
};

int main()
{
struct S s={0};

s.a = 10;
s.b = 20;
s.c = 3;
s.d = 4;
return 0;

}