定义:
结构是一些值的集合,成员类型可以不一样;
//结构体定义:
struct peo
{char name[20];int age;char sex[6];
} x, arr[20],* p;// struct peo 是自定义的类型名,类似于int ,char
// x是这个类型的全局变量,
// arr[20]是这个类型的数组
// p 是struct peo*型指针
匿名结构体:
// 匿名结构体 : 这个结构体只能使用一次
struct
{int age;char name[20];
} p1;int main()
{
//因为在创建结构体的时候已经创建了p1,所以可以用
p1={18,"lisi"};//但是我们不能再创建变量
return 0;
}
结构体与 typedef :
//结构体与 typedef(重命名)typedef struct peo
{int age;char name[20];
}peo_,* point;// 相当于 typedef struct peo peo_;// 相当于 typedef struct peo* point;// struct peo s1 == peo_ s1; peo_ 就是struct peo类型// struct peo * p == point p; point 就是struct peo* 型
结构体变量的定义与初始化:
//结构体变量的定义和初始化
// p1,p2 都是全局变量,而p3,p4,p 是局部变量struct peo
{char name[20];int age;
} p1={"lisi",18};struct peo p2 = { "zhangsan",20 };struct stu
{//结构体里面套结构体:struct peo p4;int math;int Eng;
};int main()
{struct peo s3 = { "wanger",30 };struct stu p = { {"zhuwu,24"},90,60 };printf("%s %d %d %d\n", p.p4.name, p.p4.age, p.math, p.Eng);return 0;
}
内存对齐:
(求结构体所占内存大小)
#include<stdio.h>
#include<stddef.h>
struct s1
{char c1; int i; char c2;
};
struct s2
{char c1;char c2;int i;
};int main()
{struct s1 a;struct s2 b;printf("%d\n", sizeof(a));// 12printf("%d\n", sizeof(b));// 8
// offsetof 是宏,可以求成员在结构体中的偏移量 <stddef.h>printf("%d ", offsetof(struct s1, c1));printf("%d ", offsetof(struct s1, i));printf("%d \n", offsetof(struct s1, c2));// 0 4 8printf("%d ", offsetof(struct s2, c1));printf("%d ", offsetof(struct s2, c2));printf("%d \n", offsetof(struct s2, i));// 0 1 4return 0;
}
struct s3
{double d;char c;int i;
};//16struct s4
{char c1;struct s3 S;double d;};//32
为什么这么设计呢?
其实是在用空间换取时间,当不进行对齐的时候,读取一个完整的数据要对内存做两次访问,而对齐的话,只需要进行一次访问。
为了节省空间:尽量占用空间小的成员集中在一起,
像s1和s2,虽然里面成员类型相同,但s1所占空间远大于s2。
修改默认对齐数:
使用 #pragma (一般设置为 2 的倍数)
#pragma pack(4)struct S1
{int i;double d;
};//恢复默认对齐数
#pragma pack()struct S2
{int i;double d;
};int main()
{printf("%d\n", sizeof(struct S1)); // 12printf("%d\n", sizeof(struct S2)); // 16return 0;
}
结构体传参:
struct S
{int arr[10];int i;
};void print_1(struct S as)
{for (int i = 0; i < 4; i++)printf("%d ", as.arr[i]);printf("%d\n", as.i);
}void print_2(const struct S* ps)
{for (int i = 0; i < 4; i++)printf("%d ", ps->arr[i]);printf("%d\n", ps->i);
}int main()
{struct S s1 = { {1,2,3,4},66 };//传值print_1(s1);//传地址print_2(&s1);return 0;
}
第①种是将s1的值拷贝给临时变量as,又调用了空间;
第②种是将s1的地址给ps,通过地址访问其中的每个数据,加上const 修饰,保证不能随意被修改
so 结构体传参 的时候最好 传地址