结构体(自定义类型)

野性酷女 2024-04-06 12:25 194阅读 0赞

目录

1 结构体的声明

1.1 结构的基础知识

1.2 结构的声明

1.3 特殊的声明

1.4 结构的自引用

1.5 结构体变量的定义和初始化

1.6 结构体内存对齐

1.7 修改默认对齐数


1 结构体的声明

1.1 结构的基础知识

结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。

1.2 结构的声明

  1. struct tag
  2. {
  3. member-list; //成员列表,成员变量(可一个,可多个)
  4. }variable-list;//变量列表(可选)
  5. struct book
  6. {
  7. char book_name[20];
  8. char author[20];
  9. int price;
  10. char id[15];
  11. }sb3,sb4; //全局变量
  12. int main()
  13. {
  14. struct book sb1;
  15. struct book sb2; //局部变量
  16. return 0;
  17. }

#

#

1.3 特殊的声明

在声明结构的时候,可以不完全的声明。

  1. //匿名结构体类型
  2. struct
  3. {
  4. char book_name[20];
  5. char author[20];
  6. int price;
  7. char id[15];
  8. }sb1,sb2; //全局变量
  9. int main()
  10. {
  11. return 0;
  12. }
  13. //违法,编译器会把上面的两个声明当成完全不同的两个类型
  14. struct
  15. {
  16. char book_name[20];
  17. char author[20];
  18. int price;
  19. char id[15];
  20. }sb1
  21. struct
  22. {
  23. char book_name[20];
  24. char author[20];
  25. int price;
  26. char id[15];
  27. }* ps;
  28. int main()
  29. {
  30. ps = &sb1;
  31. return 0;
  32. }

1.4 结构的自引用

  1. struct Node
  2. {
  3. int data;
  4. struct Node* next; //同类型结构体的指针
  5. };
  6. int main()
  7. {
  8. struct Node n;
  9. return 0;
  10. }
  11. typedef struct Node
  12. {
  13. int data;
  14. struct Node* next;
  15. }Node;//之前不能直接写Node
  16. int main()
  17. {
  18. Node n;
  19. return 0;
  20. }

1.5 结构体变量的定义和初始化

  1. struct book
  2. {
  3. char book_name[20];
  4. char author[20];
  5. int price;
  6. char id[15];
  7. }sb3, sb4; //全局变量
  8. int main()
  9. {
  10. struct book sb1 = {"KYF","kyf",80,"K1001"};
  11. struct book sb2; //局部变量
  12. printf("%s %s %d %s %s %d\n", sb1.book_name, sb1.author, sb1.price, sb1.id);
  13. return 0;
  14. }
  15. struct stu
  16. {
  17. char name[20];
  18. int price;
  19. };
  20. struct book
  21. {
  22. char book_name[20];
  23. char author[20];
  24. int price;
  25. char id[15];
  26. struct stu s;
  27. }sb3 = { "KY","ky",8,"K100" ,{"ASD",100}}, sb4; //全局变量
  28. int main()
  29. {
  30. struct book sb2; //局部变量
  31. printf("%s %s %d %s %s %d\n", sb3.book_name, sb3.author, sb3.price, sb3.id,sb3.s.name,sb3.s.price);
  32. return 0;
  33. }

1.6 结构体内存对齐

首先得掌握结构体的对齐规则:

  1. 第一个成员在与结构体变量偏移量为0的地址处。

  2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。

对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。

VS中默认的值为8,linux=该成员大小

  1. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。

  2. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

为什么存在内存对齐?

大部分的参考资料都是如是说的:

  1. 平台原因(移植原因):

不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特

定类型的数据,否则抛出硬件异常。

  1. 性能原因:

数据结构(尤其是栈)应该尽可能地在自然边界上对齐。

原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访

问。

总体来说:

结构体的内存对齐是拿空间来换取时间的做法。

那在设计结构体的时候,我们既要满足对齐,又要节省空间,如何做到:

让占用空间小的成员尽量集中在一起。

  1. struct S1
  2. {
  3. char c1; // 1/8 0-1
  4. int i; // 4/8 4-8
  5. char c2; // 1/8 9
  6. //4的倍数, 12
  7. };
  8. int main()
  9. {
  10. printf("%d\n", sizeof(struct S1));//12
  11. return 0;
  12. }
  13. struct S2
  14. {
  15. char c1; //1/8 0-1
  16. char c2; //1/8 1-2
  17. int i; //4/8 4-8
  18. };
  19. int main()
  20. {
  21. printf("%d\n", sizeof(struct S2));//8
  22. return 0;
  23. }
  24. struct S3
  25. {
  26. double d; //8/8 0-7
  27. char c; //1/8 7-8
  28. int i; //4/8 8-12
  29. //8的倍数
  30. };
  31. int main()
  32. {
  33. printf("%d\n", sizeof(struct S3)); //16
  34. return 0;
  35. }
  36. struct S3
  37. {
  38. double d; //8/8 0-7
  39. char c; //1/8 7-8
  40. int i; //4/8 8-12
  41. //8的倍数 16
  42. };
  43. struct S4
  44. {
  45. char c1; //1/8 0-1
  46. struct S3 s3;//8/8 8-27
  47. double d; //8/8 27-32
  48. };
  49. int main()
  50. {
  51. printf("%d\n", sizeof(struct S4)); //32
  52. return 0;
  53. }

#

1.7 修改默认对齐数

之前我们见过了 #pragma 这个预处理指令,这里我们再次使用,可以改变我们的默认对齐数。

  1. #include <stdio.h>
  2. #pragma pack(8)//设置默认对齐数为8
  3. struct S1
  4. {
  5. char c1;
  6. int i;
  7. char c2;
  8. };
  9. #pragma pack()//取消设置的默认对齐数,还原为默认
  10. #pragma pack(1)//设置默认对齐数为1
  11. struct S2
  12. {
  13. char c1;
  14. int i;
  15. char c2;
  16. };
  17. #pragma pack()//取消设置的默认对齐数,还原为默认
  18. int main()
  19. {
  20. //输出的结果是什么?
  21. printf("%d\n", sizeof(struct S1));
  22. printf("%d\n", sizeof(struct S2));
  23. return 0;
  24. }

发表评论

表情:
评论列表 (有 0 条评论,194人围观)

还没有评论,来说两句吧...

相关阅读