struct Book
{
char name[20];
int price;
char author[10];
};
int main()
{
struct Book s1 = { "C语言",18.8,"lishi" };
struct Book s2 = { .name = "python",.price = 19,.author = "zhangsan" };
}唯一用法
struct
{
char name[10];
int age;
}s1 = { "zhangsan",18 };
int main()
{
printf("%d %s", s1.age, s1.name);
return 0;
}另一个问题(指针)
struct
{
char name[10];
int age;
}s1;
struct
{
char name[10];
int age;
}* p1;
int main()
{
p1 = &s1;
return 0;
}原因:因为结构体是匿名的,编译器不认识,编译会报错

自己包含与自己相关的信息,但是不能直接包含自己类型(sizeof()没法算大小),可以包含指针 比如说链表节点的定义


typedef struct Node
{
int data;
struct Node* p;
}Node;
int main()
{
Node n1;
}补充:匿名结构体不能自引用
正确示例

错误示例

结构体大小怎么算
需要知道偏移量和对齐数的概念


嵌套结构体: 如果嵌套了结构体的情况,嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处,结构 体的整体大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍



设计结构体时尽量要让占空间小的成员挨在一起

#pragma pack(1)
struct Stu
{
char s1;
int a;
char s2;
};
#pragma pack()
int main()
{
printf("%zd", sizeof(struct Stu));
return 0;
}不适用于Linux底下,在Linux下 对齐数默认是成员自身大小
struct Stu
{
int age[100];
char name[100];
};
void Print(struct Stu s2)
{
for (int i = 0; i < 3; i++)
{
printf("%d ", s2.age[i]);
}
printf("%s ", s2.name);
}
int main()
{
struct Stu s1 = { .age = {18,19,21},.name = "zhangsan" };
Print(s1);
return 0;
}但这样会导致形参和实参占用空间,传数据也耗时间
而传地址恰恰可以解决这个问题(压栈压的是一个指针变量的大小4/8)
struct Stu
{
int age[100];
char name[100];
};
void Print(struct Stu *p)
{
for (int i = 0; i < 3; i++)
{
printf("%d ", p->age[i]);
}
printf("%s ", p->name);
}
int main()
{
struct Stu s1 = { .age = {18,19,21},.name = "zhangsan" };
Print(&s1);
return 0;
}结论: 结构体穿时,尽量传结构体的地址 传地址可能会有被改掉的风险,在前面加上形参前加上const就行了

位段的内存分配:

打开内存进行验证:

位段的应用场景:

使用位段的注意事项: 内存中每个字节分配一个地址,由内存分配知,内部的成员的起始位置不是字节的起始位置,字节内部的bit位是没有地址的 所以不能对位段的成员使用&操作符,这样就不能使用scanf直接给位段的成员输入值,只能是先输入放在一个变量中,然后赋值给位段的成员。

union S
{
char a;
int b;
};
int main()
{
union S s1;
printf("%zd", sizeof(s1));
return 0;
}联合体成员是共用一 块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联合至少得有能保存最大的那个成员) 因此改一个,全都改掉了(先改低地址处的地址)
联合体一定是最大成员的大小吗?这句话一定正确吗?
答案是:不一定


设计时如果用结构体的话,会浪费空间

可以用联合体来优化

int Check()
{
union Un
{
char a;
int b;
}s;
s.b = 1;
return s.a;
}
int main()
{
int ret = Check();
if (ret == 1)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}枚举顾名思义是一一列举,在现实生活中比如星期、性别、月份,都可以一一列举出来
enum Sex
{
Male,
Female,
Secret
};
enum Color
{
red,
green,
blue
};
int main()
{
enum Color col = red;
return 0;
}
可以使用#define,为啥要使用枚举呢?

