一·结构体介绍与书写:
首先我们来讲结构体就是一类物统称,类似于成绩单,里面记录这姓名年龄分数等;下面我们来展示代码:
struct stu {
int age;
int score;
char name [100];
}s;//这里可以定义结构体变量就不用在下面重新定义了
int main() {
/struct stu s = { 65,100,"zhangsan" };//或者还可以这样填进去/
struct stu s = { .age = 65,.name = "zhangsan",.score=100 };
printf("%d %d %s", s.age, s.score, s.name);
return 0;
}
但是为了节约内存问题,以及它的排布,我们最好选用指针来访问:
//接下来我我们来展示一下用指针访问结构体,可以节约内存的使用
struct stu {
int age;
int score;
char name[100];
};
void full(struct stu p) {
p->age = 65;
p->score = 100;
strcpy(p->name, "zhangsan");
}
void print(struct stu p) {
printf("%d %d %s", p->age, p->score, p->name);
}
int main() {
struct stu s;
full(&s);
print(&s);
return 0;
}
接下来我们介绍下结构体自引用;我们知道在存储得到连续的数字,一定要找得到它的地址使它联系起来,那么结构体也便是如此;故一个结构体中可以存放一定的数据和地址;下面我们引用一段代码来介绍一下 ;
struct Node
{
int data;
struct Node* next;
};//这里是结构体的自引用:我们在结构体里面放上数据以及一个自己类型的指针可以找到另一个结构体变量;
int main() {
struct Node a = { 1, NULL };//这里我们a不在往下找故令为null;
struct Node b = { 2, &a };//我们在这里会打印出结构体变量a的地址
printf("%d\n", b.data);
printf("%p", b.next);
return 0;
}
在这里我们就简单的实现了结构体的自引用效果;
二·结构体对齐问题:
首先结构体放入储存的时候,有一定规矩,我们来解释:
1.首先默认无论第一个成员是什么类型我们都放在对齐数为0的地方;然后之后的成员我们要根据类型判断字节数然后放在对齐数为它和编译器默认的值的最小值排放,然后后面的依次这样。(这里我们说明一下在vs默认值是8;gcc等为对齐数本身大小。
2.我们最后排放完后,数字节数时,它的对齐数一定要是成员中最大对齐数的整数倍。
3.但是可能也会有结构体嵌套结构体类型,那么这个成员结构体的对齐数是这个被嵌套的结构体所
有成员中对齐数最大的倍数,最终这个外面的结构体的字节数就是他的所有成员对齐数的整数倍(包括被嵌套的结构体里面的成员)。
下面我们来用代码解释一下:
struct S {
char a;
int i;
char t;
}s;
int main() {
printf("%zd", sizeof(s));
}
肯定会疑惑这里为什么是12呢;接下来我们来画图解释一下结构体储存的原理:
接下来我们来介绍一下结构体嵌套自己求法:
struct S {
char a;
int i;
char t;
}s;
struct k {
int m;
struct S s;
char p;
}n;
int main() {
printf("%zd", sizeof(n));
}
这里我们画图解释一下:
那么他会打印出:
三·结构体位段问题:
我们首先介绍一下位段简单概念就是给结构体内的成员分配比特位;然后我们就限制了它在内存中的存储大小;下面我们用代码和图片展示一下
当然它的使用也存在跨平台问题:
如我们int 位段的有无符号是不确定的;最大位段的数也是不同(如16位机器是16,32位机器是32,写错是会出问题的);其次就是位段储存数不知是从右往左还是从左往右;舍弃问题也是如此,当我们对位段的数取地址,由于它们是分配储存不一,故无法找到正确的地址。