合肥市蜀山区建设局网站,wordpress square主题,网站上传,我要做一个网站 需要营业范围吗目录
前言
一、定义结构
结构体变量的创建和初始化
二、结构的特殊声明
特别注意#xff1a;
结构的⾃引⽤
三、结构体内存对⻬
对⻬规则
优化结构体
#pragma
结构体传参
四、结构体实现位段
位段的内存分配
位段的跨平台问题 前言
C 数组允许定义可存储相同类…
目录
前言
一、定义结构
结构体变量的创建和初始化
二、结构的特殊声明
特别注意
结构的⾃引⽤
三、结构体内存对⻬
对⻬规则
优化结构体
#pragma
结构体传参
四、结构体实现位段
位段的内存分配
位段的跨平台问题 前言
C 数组允许定义可存储相同类型数据项的变量结构是 C 编程中另一种用户自定义的可用的数据类型它允许您存储不同类型的数据项。
结构体中的数据成员可以是基本数据类型如 int、float、char 等也可以是其他结构体类型、指针类型等。 一、定义结构
结构体定义由关键字 struct 和结构体名组成结构体名可以根据需要自行定义。
结构是⼀些值的集合这些值称为成员变量。结构的每个成员可以是不同类型的变量。
例如 struct Stu { char name[20];//名字 int age;//年龄 char sex[5]; char id[20];//学号 }; 结构体变量的创建和初始化 #include stdio.h struct Stu { char name[20];//名字 int age;//年龄 char sex[5];//性别 char id[20];//学号 }; int main() { //按照结构体成员的顺序初始化 struct Stu s { 张三, 20, 男, 20230818001 }; printf(name: %s\n, s.name); printf(age : %d\n, s.age); printf(sex : %s\n, s.sex); printf(id : %s\n, s.id); //按照指定的顺序初始化 struct Stu s2 { .age 18, .name lisi, .id 20230818002, .sex ⼥ }; printf(name: %s\n, s2.name); printf(age : %d\n, s2.age); printf(sex : %s\n, s2.sex); printf(id : %s\n, s2.id); return 0; } 二、结构的特殊声明 在声明结构的时候可以不完全的声明。 ⽐如 // 匿名结构体类型 struct { int a; char b; float c; }x; struct { int a; char b; float c; }a[ 20 ], *p; 特别注意 编译器会把上⾯的两个声明当成完全不同的两个类型所以是⾮法的。 匿名的结构体类型如果没有对结构体类型重命名的话基本上只能使⽤⼀次。 结构的⾃引⽤ 例如定义⼀个链表的节点 struct Node { int data; struct Node next; }; 仔细分析其实是不⾏的因为⼀个结构体中再包含⼀个同类型的结构体变量这样结构体变量的⼤ ⼩就会⽆穷的⼤是不合理的。 正确的⾃引⽤⽅式 struct Node { int data; struct Node* next; }; 三、结构体内存对⻬ 对⻬规则 ⾸先得掌握结构体的对⻬规则 1. 结构体的第⼀个成员对⻬到和结构体变量起始位置偏移量为0的地址处 2. 其他成员变量要对⻬到某个数字对⻬数的整数倍的地址处。 对⻬数 编译器默认的⼀个对⻬数 与 该成员变量⼤⼩的较⼩值。 - VS 中默认的值为 8 - Linux中 gcc 没有默认对⻬数对⻬数就是成员⾃⾝的⼤⼩ 3. 结构体总⼤⼩为最⼤对⻬数结构体中每个成员变量都有⼀个对⻬数所有对⻬数中最⼤的的 整数倍。 4. 如果嵌套了结构体的情况嵌套的结构体成员对⻬到⾃⼰的成员中最⼤对⻬数的整数倍处结构 体的整体⼤⼩就是所有最⼤对⻬数含嵌套结构体中成员的对⻬数的整数倍。 优化结构体 那在设计结构体的时候我们既要满⾜对⻬⼜要节省空间如何做到 //例如 struct S1 { char c1; int i; char c2; }; struct S2 { char c1; char c2; int i; }; #pragma #pragma 这个预处理指令可以改变编译器的默认对⻬数。 #include stdio.h #pragma pack(1)//设置默认对⻬数为1 struct S { char c1; int i; char c2; }; #pragma pack()//取消设置的对⻬数还原为默认 int main() { printf(%d\n, sizeof(struct S)); return 0; } 结构体传参 struct S { int data[ 1000 ]; int num; }; struct S s {{ 1 , 2 , 3 , 4 }, 1000 }; // 结构体传参 void print1 ( struct S s) { printf ( %d\n , s.num); } // 结构体地址传参 void print2 ( struct S* ps) { printf ( %d\n , ps-num); } int main () { print1(s); // 传结 构体 print2(s); // 传地址 return 0 ; } print2函数是要优于print1函数的 原因 函数传参的时候参数是需要压栈会有时间和空间上的系统开销。 如果传递⼀个结构体对象的时候结构体过⼤参数压栈的的系统开销⽐较⼤所以会导致性能的下降 总结 结构体传参的时候要传结构体的地址。 四、结构体实现位段 位段的声明和结构是类似的有两个不同 1. 位段的成员必须是 int 、 unsigned int 或 signed int 在C99中位段成员的类型也可以 选择其他类型。 2. 位段的成员名后边有⼀个冒号和⼀个数字。 例如 struct A { int _a:2; int _b:5; int _c:10; int _d:30; }; 位段的内存分配 1. 位段的成员可以是 int unsigned int signed int 或者是 char 等类型 2. 位段的空间上是按照需要以4个字节 int 或者1个字节 char 的⽅式来开辟的。 3. 位段涉及很多不确定因素位段是不跨平台的注重可移植的程序应该避免使⽤位段。 struct S { char a:3; char b:4; char c:5; char d:4; }; struct S s {0}; s.a 10; s.b 12; s.c 3; s.d 4; 位段的跨平台问题 1. int 位段被当成有符号数还是⽆符号数是不确定的。 2. 位段中最⼤位的数⽬不能确定。16位机器最⼤1632位机器最⼤32写成27在16位机器会 出问题。 3. 位段中的成员在内存中从左向右分配还是从右向左分配标准尚未定义。 4. 当⼀个结构包含两个位段第⼆个位段成员⽐较⼤⽆法容纳于第⼀个位段剩余的位时是舍弃 剩余的位还是利⽤这是不确定的。 总结 跟结构相⽐位段可以达到同样的效果并且可以很好的节省空间但是有跨平台的问题存在。