本章重点:
结构体:
1 结构体的声明
1.1 结构的基础知识
1.2 结构的声明
// struct tag
// {
// member-list;
// }variable-list; //变量列表
struct Stu
{
int age;
char name[20];
char id[20];
};
struct Stu s1,s2,s3;
1.3 特殊的声明
在声明结构的时候吗可以不完全声明
//特殊声明
struct
{
int a;
char c;
float f;
} x;
struct
{
int a;
char c;
float f;
}* p;
int main()
{
//p = &x; //err
return 0;
}
1.4 结构体的自引用
// struct Node
// {
// int data;
// struct Node* next;
// };
// typedef struct //err
// {
// int data;
// Node* next;
// } Node;
typedef struct Node
{
int data;
struct Node* next;
} Node;
int main()
{
Node n = {0};
return 0;
}
1.5 结构体变量的定义和初始化
struct SN
{
//char c[20];
char c;
int i;
}sn1 = {'q',100},sn2 = {.i=50,.c='w'}; //全局变量
struct S
{
double d;
struct SN sn;
int arr[10];
};
int main()
{
//struct SN sn3,sn4; //局部变量
//printf("%c %d\n",sn2.c,sn2.i);
//printf("%c %d\n",sn1.c,sn1.i);
struct S s = {3.14,{'a',99},{1,2,3,4}};
printf("%lf %c %d\n",s.d,s.sn.c,s.sn.i);
int i = 0;
for (i = 0; i< 10;i++)
{
printf("%d ",s.arr[i]);
}
return 0;
}
1.6 结构体内存对齐
// struct S1
// {
// char c1;
// int i;
// char c2;
// };
// struct S2
// {
// int i;
// char c1;
// char c2;
// };
// int main()
// {
// printf("%d\n",sizeof(struct S1)); //12
// printf("%d\n",sizeof(struct S2));// 8
// printf("%d\n",offsetof(struct S1,c1));//可以计算结构体成员相较于结构体起始位置的偏移量 //0
// printf("%d\n",offsetof(struct S1,i));//4
// printf("%d\n",offsetof(struct S1,c2));//8
// printf("%d\n",offsetof(struct S2,i));//可以计算结构体成员相较于结构体起始位置的偏移量 //0
// printf("%d\n",offsetof(struct S2,c1));//4
// printf("%d\n",offsetof(struct S2,c2));//8
// //通过上面的现象分析,我们发现结构成员不是按照顺序在内存中连续存放的,而是有一定的对齐规则的
// return 0;
// }
struct S3
{
double d;
char c;
int i;
};
struct S4
{
char c1;
struct S3 s3;
double d;
};
int main()
{
printf("%d\n",sizeof(struct S4)); //32
return 0;
}
1.7 修改默认对齐数
#pragma pack(1)
struct S
{
char c1;// 1 1 1
int a;// 4 1 1
char c2;// 1 1 1
};
#pragma pack(1)
int main()
{
printf("%d\n",sizeof(struct S));
return 0;
}
1.8 结构体传参
struct S
{
int data[100];
int num;
};
void print1(struct S tmp)
{
printf("%d\n",tmp.num);
}
//优先使用结构体传参
void print2(struct S* ps)
{
printf("%d\n",ps->num);
}
int main()
{
struct S s = {{1,2,3},100};
print1(s);
print2(&s);
return 0;
}
2. 位段
2.1 什么是位段
struct A
{
int _a : 2; //二进制位
int _b : 5;
int _c : 10;
int _d : 30;
};
int main()
{
printf("%d\n",sizeof(struct A));
return 0;
}
2.2 位段的内存分配
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 = 12;
s.c = 3;
s.d = 4;
printf("%d\n",sizeof(struct S));
return 0;
}
2.3 位段的跨平台问题
枚举:
3.1 枚举类型的定义
enum Color
{
RED,
GREEN = 8,
BLUE
};
int main()
{
enum Color c = GREEN;
printf("%d\n",RED);
printf("%d\n",GREEN);
printf("%d\n",BLUE);
return 0;
}
3.2 枚举的优点
3.3 枚举的使用
enum Color
{
RED = 1,
GREEN = 8,
BLUE = 4
};
int main()
{
// enum Color c = GREEN;
// printf("%d\n",RED);
// printf("%d\n",GREEN);
// printf("%d\n",BLUE);
enum Color clr = GREEN;
clr = 5;
return 0;
}
联合:
4.1 联合类型的定义
union Un
{
char c;
int i;
};
int main()
{
printf("%d\n",sizeof(union Un));
union Un un = {0};
printf("%p\n",&un);
printf("%p\n",&un.i);
printf("%p\n",&un.c);
return 0;
}
4.2 联合的特点
union Un
{
char c;
int i;
};
int main()
{
printf("%d\n",sizeof(union Un));
union Un un = {0};
un.i = 0x11223344;
un.c = 0x55;
printf("%x\n", un.i);
// printf("%p\n",&un);
// printf("%p\n",&un.i);
// printf("%p\n",&un.c);
return 0;
}
4.3 联合的计算
// union Un
// {
// int i;
// char c;
// };
// int main()
// {
// printf("%d\n",sizeof(union Un)); //4
// return 0;
// }
// int check_sys()
// {
// union
// {
// int i;
// char c;
// } un = {.i = 1};
// return un.c;
// }
// int main()
// {
// int ret = check_sys();
// if(ret ==1)
// {
// printf("小端\n");
// }
// else
// {
// printf("大端\n");
// }
// return 0;
// }
union Un1
{
char c[5]; //5 1 8 1
int i; //4 8 4
};
union Un2
{
short c[7]; //14 2 8 2
int i; //4 4 8 4
};
int main()
{
printf("%d\n",sizeof(union Un1)); //5 + 3 = 8
printf("%d\n",sizeof(union Un2)); //14 + 2 = 16
return 0;
}