结构体
结构体:结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。
结构体的声明
struct Student {
char name[20]; //姓名
char sex[2]; //性别
int age; //年龄
char colleage[20]; //学校
char clazz[20]; //班级
};
结构体的变量的定义和初始化
struct Point {
int x;
int y;
}p1;
struct Point p2;
struct Point p3 = { 1,2 };
struct Node {
int data;
struct Point p; //嵌套结构体
struct Node* next;
}n1 = { 1,{1,3},NULL };
struct Node n2 = { 4,{5,
结构体内存对齐
计算结构体的内存对齐的规则:
- 第一个成员在与结构体变量偏移量为0的地址处。
- 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
- 对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
1. VS中默认的值为8
2. Linux中默认的值为4 - 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
- 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体对齐数)的整数倍。
struct S1
{
char c1;
int i;
char c2;
};
根据下面的图可以看出此结构体的内存对齐数为:12(要为最大对齐数的整倍数)
struct S2
{
char c1;
char c2;
int i;
};
struct S3
{
double d;
char c;
int i;
};
struct S4
{
char c1;
struct S3 s3;
double d;
};
对齐图省略不画,要画32个格子 笔者会吐血。
对齐数为:32
- 此外;我们也可以修改对齐数:
利用:#pragma pack()设置对齐数
#pragma pack(8) //设置默认对齐数为8
#pragma pack() //恢复默认对齐数
结构体传参
#include<stdio.h>
#include<stdlib.h>
typedef struct S {
int data[1000];
int num;
}S;
print(struct S tmp) {
int i = 0;
for (i = 0; i < 5; i++) {
printf("%d ", tmp.data[i]);
}
printf("\n");
printf("num=%d", tmp.num);
}
int main() {
S s = { {1,2,3,4,5,6},8 };
print(s);
return 0;
}
结构体位段
- 位段的使用规则:
1.位段的成员必须是 int、unsigned int 或signed int
2.位段的成员名后边有一个冒号和一个数字。
struct A{
int a:2; //占两个bit位
int b=5; //占5个bit位
int c=10; //占10个bit位
int d=30; // 占30个bit位
}
4字节=32比特
而 a+b+c=17<32;可以公用一个int型所占据的空间,而d的比特数为:30,自己可以独享一个int型空间,所哟此结构体要占据空间为:8个字节
struct S
{
char a:3; //占据三个bit位
char b:4; //占据四个bit位
char c:5; //占据五个bit位
char d:4; //占据四个bit位
};
struct S s = {0};
s.a = 10;
s.b = 12;
s.c = 3;
s.d = 4;
a:10的二进制数:1010
b:12的二进制数:1100
c:3的二进制数:011
d:4的二进制数:100
联合体
联合体的定义:
联合也是一种特殊的自定义类型 这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间(所以
联合也叫共用体)。
联合体大小的计算:
- 联合的大小至少是最大成员的大小。
- 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
联合体的声明:
union un
{
char c;
int i;
};
利用联合体判断计算机存储的大小端模式
#include<stdio.h>
#include<stdlib.h>
int checkSystem() {
union U {
char c;
int i;
}u;
u.i = 1;
//返回1的时候是小端
//返回0的时候是大端
return u.c;
}
int main() {
if (checkSystem == 1) {
printf("小端\n");
}
else {
printf("大端\n");
}
return 0;
}