开发网站去哪里学,seo快速优化文章排名,客户关系管理案例经典,wordpress cd结构体类型 为什么要有结构体 我们用c语言描述年龄时候#xff0c;可以定义一个整形类型来实现#xff1a;
int age;
age 18;
printf(年龄为%d,age);
(c语言描述年龄) 由于年龄这一属性比较单一#xff0c;类似性别、某游戏角色攻击力、血量都可以用c语言内置…结构体类型 为什么要有结构体 我们用c语言描述年龄时候可以定义一个整形类型来实现
int age;
age 18;
printf(年龄为%d,age);
(c语言描述年龄) 由于年龄这一属性比较单一类似性别、某游戏角色攻击力、血量都可以用c语言内置的变量来描述。 但是如果现在需要描述一本书或一个游戏装备这种有多种属性的角色只用一个变量看起来就不够用了我们需要一种方式结构体来描述他们 例如描述一本书我们可以这样说“书的名字是xxx书的作者是xxx书的总页数是xxx”这时我们需要定义一个结构体类型以描述这些属性。 结构体类型定义初始化使用 结构体定义 以下是定义一个用来描述书的结构体类型模样如下
//struct 表示结构体 book 表示结构体类型名称
struct book
{//此处为自定义结构体类型“book” 的属性们char name[20]char writer[20];int n;
}结构体初始化
//前面定义了结构体变量类型现在用定义好的类型创建一个结构体
struct book doom; //wtruct book表示类型 “doom”表示结构体变量名//结构体初始化类似于普通变量的初始化
int a; //“int”表示类型 “a”表示变量名doom.n 30;//赋值结构体doom中的n书的页数strcpydoom.name,老人与海//f赋值结构体doom中的name书名结构体使用
printf(%d,doom.n);//打印书的页数
结构体对齐 为什么要有结构体对齐 假如我们现在有这样的一个结构体
struct test//定义类型
{char a;int b;int c;int d;
}struct test A;//创建一个结构体A 我们可能想象的A在内存中是这样放的 对于我们来说一目了然但是对于计算机读取来说就麻烦了假如现在有一个机器他一次可以读四个字节那么他访问结构体A可能需要七次才能读完 我们可以通过某种规则让他变成方便计算机读取的存储形式 空间换时间用三个字节的代价让计算机读取这个结构体用的次数减少了三次。 对齐规则 以下是结构体对齐规则的基本要点 首个成员对齐 结构体的第一个成员总是从结构体变量的起始地址开始存放偏移量为0。 成员对齐规则 后续每个成员在结构体中的偏移量需要是对齐数的整数倍其中对齐数一般等于该成员的大小或编译器默认的对齐数机器相关的最小对齐单位两者中的较小值。比如如果一个结构体里有一个int成员而在当前平台上int大小为4字节且默认对齐单位也为4字节那么该int成员将被放在4字节对齐的位置上。 结构体大小对齐 结构体的总大小包括可能存在的填充字节需要是所有成员中最大对齐数的整数倍。结构体末尾可能会添加额外的字节作为填充以满足上述对齐要求。 结构体自身的对齐值 结构体的有效对齐值通常是其所有成员中最大对齐值的成员的对齐值确保整个结构体实例的起始地址也符合这个最大对齐值的要求。当结构体组成数组时结构体之间的间隔也将按照结构体的有效对齐值来确定。 编译器控制 许多编译器允许通过预编译指令如C/C中的#pragma pack(n)来指定自定义的对齐值这样会暂时改变当前作用域内的结构体对齐策略。 结构体位段 为什么要有结构体位段 假如有这样的一个结构体类型
//类型名称考试成绩
struct Scores
{int mathint englishint chinese
} 一般来说一个成绩只需要三位数就可以描述也就是只需要八个机器码比特完全够用了而一个int类型要占用32个机器码比特这样就显得很浪费了。 为了解决这个问题节省空间我们可以使用结构体位段。简单来说就是让变量们挤一挤。比如上面的Scores结构体让三科的成绩挤在一个整形int里。 这样浪费的空间就少了很多用位段定义这个成绩结构体类型如下
struct Scores
{int :math;int :english;int :chinese;
}结构体位段规则不同编译器有所差异 结构体位段Bit-field是C语言中一种特殊的数据结构允许在一个整型变量通常为int或unsigned int内划分多个命名的位区域。位段的规则主要包括 声明格式 在结构体中定义位段时格式如下: struct {type member_name : bit_width;// 其他位段...
} variable_name; 其中type是位段成员的类型但实际存储时会被隐式转换为足够容纳所有位段的整型类型member_name是位段的名称bit_width是在该位段中使用的位数。 分配顺序 位段成员在内存中按照声明顺序从左向右分配但不同的编译器可能会有不同的分配策略有的是从最低有效位LSB开始分配有的是从最高有效位MSB开始分配。 位段宽度 bit_width指定的位数不能超过成员类型的位宽。例如在32位系统中一个int类型的位段的宽度范围是1到32。 未指定宽度 如果省略位宽则大多数编译器会根据成员类型自动选择合适的位宽直到填满包含位段的整数。 存储开销 编译器会尽可能紧凑地安排位段但可能会在位段之间加入额外的位作为填充以便于整体对齐并且至少会分配一个完整的基本整型变量的空间如一个int来存储所有位段。 跨边界行为 不同编译器对于位段跨越一个基本整型变量边界的处理方式不同。有些编译器会在下一个整型变量中继续分配而有些则可能不支持跨越边界。 初始化和赋值 可以初始化位段但赋值时要注意仅修改指定位段的位不会影响同一存储单元内其他位段的值。 跨平台差异 位段的具体行为依赖于编译器实现因此在不同平台和编译器之间可能存在显著差异编写可移植的位段代码时需特别小心。