1.结构体定义
用struct将不同的类型的数据组成的整体,这种类型称为结构体类型。
结构体是一种构造类型的数据结构,
是一种或多种基本类型或构造类型的数据的集合。
2.结构体的定义和初始化
定义结构体变量的方式:
- 先声明结构体类型再定义变量名
- 在声明类型的同时定义变量
方法一:先声明结构体类型,再定义变量名
(1)第一步
struct 结构体名{
成员列表
}
(2)第二步
struct 结构体名 变量名
方法二:定义结构体类型的同时,定义变量
struct 结构体名{
成员列表
}变量名;
方法三:定义结构体类型的同时,定义变量
struct {
成员列表
}变量名1,变量名2;
//也可以用typedef创建新类型 后续会用到
typedef struct{
int a;
char b;
double c;
} Simple2;
struct Person struct Person P1
{ char name[20]; { "Nancy",
int age; --> 18,
........ .........
}; };
3.结构体成员的访问
结构体成员的使用,分为两种情况:
1、通过结构体变量访问成员 语法:结构体变量名.成员
2、通过结构体指针变量访问 语法:结构体指针变量->成员
说明:
1.在创建一个结构体变量后,需要给成员赋值。在没有给成员赋值的情况下调用,打印的值是垃圾数据,可能导致程序异常终止。
2.不同结构体变量的成员是独立的,互不影响,一个结构体变量的成员更改,不影响另外一个。
总结:区分三个概念:结构体、结构 体变量、结构体变量的成员。
- 结构体是自定义的数据类型, 表示的是一种数据类型。
- 结构体变量代表一个具体变量。
int num1; //int 是数据类型 而num1是一个具体的int变量struct Car car1;// Car 是结构体数据类型 ,而car1是一个Car变量
4.结构体的嵌套
单链表结构的结点定义如下:
stuct Node{
int data; //这里默认的是int型,如需其它类型可修改
struct Node *next; //指向node型变量的指针
}
二叉树结构的结点定义如下:
typedef struct BTNode{
int data; //这里默认的是int型,如需其它类型可修改
struct BTNode *lchild;//指向左孩子结点指针
struct BTNode *rchild;//指向右孩子结点指针
} BTNode;
5.结构体的内存大小
首先得掌握结构体的对齐规则:
1. 第一个成员在与结构体变量偏移量为 0 的地址处。
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
默认对齐数 成员对齐数(成员大小)
对齐数=默认对齐数 VS 成员对齐数(成员大小)中的较小值
对齐数 = 编译器默认的一个对齐数 与 该成员大小的 较小值
VS 中默认的值为 8
linux中默认值为 4
3. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
struct num
{ // 默认对齐数 成员对齐数 对齐数(最小值)
double a;// 8 8 8 a占了8位
char b;// 8 1 1 b也占了8位,实际只占了1位,有7位空着
int c;// 8 4 4 b空出来的7位刚好够c的大小,所以c占b的后四位
char d;// 8 1 1 d单独占8位 综上,num占3*8=24位
//综上,求出最大对齐数位8,结构体总大小为最大对齐数的整数倍。
};
int main()
{
struct num num1;
printf("%zu\n", sizeof(num1));//24
printf("%p\n", &num1.a);//000000E391AFF7B8
printf("%p\n", &num1.b);//000000E391AFF7C0
printf("%p\n", &num1.c);//000000E391AFF7C4
printf("%p\n", &num1.d);//000000E391AFF7C8
return 0;
}
可以根据运行结构看到结构体里面的这个数据a,b,c,d的地址,各自所占字节数确实是和开始预设的一样,最终num1所占的内存位24位,也和自己算的一样。