知识点:
1.结构体类型创建
对结构体类型tag声明:
struct tag { int a; int c; };
在声明结构体的时候,可以不完全声明
比如
// 匿名结构体类型 struct { int a; char b; float c; }x; struct { int a; char b; float c; }a[20], *p;
上面的两个结构体在声明的时候省略掉了结构体标签(tag)
那么问题来了?
// 在上面的代码的基础上,下面的代码合法吗? p = &x;
警告:
编译器会把上面两个声明当成完全不同的两个类型
所以是非法的.
2.结构体初始化
结构体初始化需要访问其成员变量
结构体变量访问成员 ,结构变量的成员是通过(.)访问的,点操作符接受两个操作数。
例如:
struct stu { char name[20]; int age; }; struct stu s;//定义结构体变量
我们可以看到s有成员name和age;
那我们如何访问s的成员?
struct stu s; strcpy(s.name,"zhangsan");//使用.访问name成员 s.age=20;//使用.访问age成员
结构体访问指向变量的成员 ,有时候我们得到的不是一个结构体变量,而是指向一个结构体变量的结构体指正。那该如何访问成员。如下:
struct S { char name[20]; int age; }s; void print(struct S* ps) { printf("name = %s age = %d\n", (*ps).name, (*ps).age); printf("name = %s age = %d\n", ps->name, ps->age); }
结构体的自引用
在结构体中包含一个类型为改结构体本身的成员是否可以呢?
struct Node { int data; struct Node next; }; // 是否可行? 如果可以sizeof(struct Node)是多少?
显然是不可以的,如果可行sizeof(struct Node)的大小完全无法计算。
正确的自引用方式:
// 代码 struct Node { int data; struct Node* next; };注意
//代码3 typedef struct { int data; Node* next; }Node; // 这样写代码,可行否? //解决方案: typedef struct Node { int data; struct Node* next; }Node;
代码3的第一种写法中Node* next执行在 typedef之前,对与编译器而言此时Node是未定义的标识符
结构体的不完整声明
struct A { int _a; struct B* pb; }; struct B { int _b; struct A* pa; }; //可行否?一般来说这是不合语法的,不能编译通过,但是有些编译器很智能,可以编译通过
解决方案:
struct B; struct A { int _a; struct B* pb; }; struct B {
int _b; struct A* pa; };
对B不完整声明即可。
结构体的变量的定义和初始化
结构体的变量的定义和初始化
struct Point { int x; int y; }p1; // 声明类型的同时定义变量p1 struct Point p2; // 定义结构体变量p2 // 初始化:定义变量的同时赋初值 struct Point p3 = {x, y}; struct Stu // 类型的声明 { char name[15];// 名字 int age; // 年龄 }; struct Stu s = {"zhangsan", 20};// 初始化 struct Node { int data; struct Point p; struct Node* next; }n1 = {10, {4,5}, NULL}; // 结构体嵌套初始化 struct Node n2 = {20, {5, 6}, NULL};// 结构体嵌套初始化
3.结构体内存对齐
1.第一个成员在与结构体变量偏移量为0的地址处
2.其他成员变量要对齐到某个数组(对齐数)的整数倍的地址处。对齐数=编译器默认的一个对齐数与该成员大小的较小值。VS中默认的值为8 Linux中的默认值为4
3.结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
4.位段,位段计算机大小。