![[Pasted image 20251126163743.png]]
```
|   |
|---|
|//struct Book|
||//{|
||// char name[20];|
||// char author[20];|
||// float price;|
||// char id[13];|
||// //...|
||//}b3, b4;//全局变量|
||//|
||//struct Book b2;//全局变量|
||//|
||//int main()|
||//{|
||// struct Book b1;//局部变量|
|// struct Book arr[5];//数组|//数组也是可以的
||//|
||// return 0;|
||//}|
|||
```
![[Pasted image 20251126164536.png]]
匿名,结构体没有名字,但是可以创建变量s依旧可以使用一次,不能再使用创建其他变量,打印
可以用s.c, 也可以用s->c,一样的
```
/struct 
//{
//    char c;
//    int i;
//    double d;
//} s = {'x', 100, 3.14};
//
//int main()
//{
//    printf("%c %d %lf\n", s.c, s.i, s.d);
//
//    return 0;
//}
//typedef struct
//{
//    char c;
//    int i;
//    double d;
//}S;
//
//int main()
//{
//    S s;
//    return 0;
//}
//没意义,但是可以的

```
#结构体的自引用
链表
数据结构,数据在内存种存储组织和结构
数据结构有多种,线性,顺序表,链表,栈,队列
树形,二叉树

![[Pasted image 20251126165602.png]]
![[Pasted image 20251126165859.png]]
定义一个节点包含数据和下一个数据的地址
就是数据域和指针域
最后一个空指针
```
|   |
|---|
|//struct Node|
||//{|
||// int data;//数据|
||// struct Node* next;//指针|
||//};|
||//|
```
![[Pasted image 20251126172906.png]]
米的天,为什么
结构体内存对齐
![[Pasted image 20251126215913.png]]
前提引入
```
|//struct S|
||//{|
||// char c1;//1|
||// int i;//4|
||// char c2;//1|
||//};|
|||
```
%zd打印无符号整型
![[Pasted image 20251126220201.png]]
规则(为什么是12)
四条规则
偏移量
![[Pasted image 20251126220335.png]]
![[Pasted image 20251126221231.png]]
打印12个字节
这个怎么说,结构体的第一个成员对其结构体变量起始位置偏移量为0的地址,
其他成员变量对其到(对齐数)的整数倍的地址处
对齐数就是与编译器的对齐数比较较小的值
结构体总大小为最大对齐数的整数倍
9不是4的倍数,12是,那就是打印出12
那么其实真实的浪费了六个字节
```
|   |
|---|
|//struct S2|
||//{|
||// char c1;|
||// char c2;|
||// int i;|
||//};|
```
打印8个字节
![[Pasted image 20251126222515.png]]
  ```
  |   |
|---|
|//struct S3|
||//{|
||// double d;//8 8 8|
||// char c; //1 8 1|
||// int i; //4 8 4|
||//};|
  ```
  
  ```
  |   |
|---|
|//struct S4|
||//{|
||// char c1;|
||// struct S3 s3;|
||// double d;|
||//};|
  ```
  ![[Pasted image 20251126224116.png]]
  如果嵌套了结构体的情况,嵌套的结构题成员对其到自己成员中最大的对齐数的整数倍处,结构体的整体大小就是使用最大对齐数的整数倍
  在嵌套的结构体里取最大的对齐数,8,不是直接取16
  所以32是8的倍数
  **为什么存在内存对齐**
  ![[Pasted image 20251127092837.png]]
  对齐后,读一次(在4的倍数那里读取)就能得到数据
  需要既满足对齐,又满足节省空间
  用存放位置安排,把小的成员集中在一起
  #修改默认对齐数
  # pragma pack(1)//设置默认对齐数
  # pragma pack()//取消设置默认对齐数,还原成默认
  ```
  |   |
|---|
|//#pragma pack(1)|//可以改成2的次方,这是2的零次方
||//struct S|
||//{|
||// char c1;//1 1 1|
||// int i; //4 1 1|
||// char c2;//1 1 1|
||//};|
|   |
|---|
|//#pragma pack()|
||//|
||//|
||//int main()|
||//{|
||// printf("%zd\n", sizeof(struct S));|
||//|
||// return 0;|
||//}|
  ```
  #结构体传参
  ```
  |   |
|---|
|//int main()|
||//{|
||// struct S s = { {1,2,3,4,5}, 100, 3.14 };|
||// //print1(s);|
||// print2(&s);|
||//|
||// return 0;|
||//}|
  ```
  ![[Pasted image 20251127094930.png]]
  ```
  |   |
|---|
|/struct S|
||//{|
||// int arr[1000];|
||// int n;|
||// double d;|
||//};|
||//|
// //void print1(struct S tmp)
//{
//    int i = 0;
//    for (i = 0; i < 5; i++)
//    {
//        printf("%d ", tmp.arr[i]);
//    }
//    printf("%d ", tmp.n);
//    printf("%lf\n", tmp.d);
//}
// 

|   |
|---|
|/void print2(const struct S* ps)|
||//{|
||// int i = 0;|
||// for (i = 0; i < 5; i++)|
||// {|
||// printf("%d ", ps->arr[i]);|
||// }|
||// printf("%d ", ps->n);|
||// printf("%lf ", ps->d);|
||//}|
||//|


//int main()
//{
//    struct S s = { {1,2,3,4,5}, 100, 3.14 };
//    //print1(s);
//    print2(&s);
//
//    return 0;
//}
  ```
  ![[Pasted image 20251127224613.png]]
  优先选择第二个函数,因为如果传的是结构体对象,结构体过大参数压栈的协同开销比较大,会导致性能下降
  所以结构体传参尽量传的是结构体的地址
  #位段式结构
  位段是基于结构体实现的
  位段的声明和结构是类似的,但也有不同
  1 位段的成员必须是int unsigned int 或者signed int,
  2 位段的成员名后边有个冒号和数字
  ```
  |   |
|---|
|/位段式的结构|
||//struct S|
||//{|
||// int _a:2;|
||// int _b:5;|
||// int _c:10;|
||// int _d:30;|
||//};|
  ```
  位段式结构
  1 申请到的的一块内存中,从左往右还是从右往左使用,是不确定的,在vs环境种是从右往左
  2 剩余的空间,不足下一个成员使用的时候,是浪费还是继续使用,也是不确定的,但是在vs环境,是浪费
  ![[Pasted image 20251127205602.png]]
  ![[Pasted image 20251127205625.png]]
  这个3怎么来的
  三是三个字节,是使用三个字节
  3* 8=24个比特位
  ![[Pasted image 20251127205725.png]]
  这个图是重点
  下面的620304是16进制的地址
  ![[Pasted image 20251127205821.png]]
  刚好小端存放
  位段式结构的好处就是节省空间
  位段的跨平台问题
  一堆不确定
  ![[Pasted image 20251127225506.png]]
  #位段的注意事项
  位段的成员共有同一个字节的,这样有些成员的起始位置并不是某个字节的起始位置,那么这些位置处就没有地址,内存中每个字节分配一个地址,一个字节内部的bit位是没有地址的
  所以不能对位段的成员使用取地址&符号,这样就不能使用是scanf直接给位段的成员输入值,之呢个是先输入放在一个变量中,然后赋值的位段大的成员
  ```
  |   |
|---|
|//int main()|
||//{|
||// struct A sa = { 0 };|
||// //scanf("%d", &(sa._b));//这是错误的|
||//|
||// //正确的示范|
||// int b = 0;|
||// scanf("%d", &b);|
||// sa._b = b;|
||//|
||// return 0;|
||//}|
  ```

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐