C语言---自定义类型:结构体(4)

简介: C语言---自定义类型:结构体

C语言---自定义类型:结构体(3)https://developer.aliyun.com/article/1544453

位段的内存分配

那么位段时如何改变内存的分配的呢?

  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;
//};
//int main()
//{
//    struct S s;
//
//    return 0;
//}
/*
因为这里的数据是char类型的,1个字节,8个比特位
那么我们先开辟8个比特位,我们先用,不够的话再开辟
 
1.给定了空间后,在空间内部是从左向右使用还是从右向左使用呢?这个是不确定的
c语言并没与规定这个方向
 
 
那么我们假设从右到左
 1  2  3  4  5  6  7  8---这里表示的是比特位的位置
    b  b  b  b  a  a  a
 
 
    放完a和b还只有一个比特位了,不够的话我们再开辟一个字节
 
 
    2.当剩下的空间不足以存放喜爱一个成员的时候,空间是浪费还是使用,这个是不确定的
    那么我们就假设:是浪费
    //那么1号位就浪费了
1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16
   b  b  b  b  a  a  a              c   c   c   c   c
 
 
   放完c之后,就放d,d要4个比特位,但是现在只剩下3个比特位了
   那我们就再次开辟一个字节
 
1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24 
   b  b  b  b  a  a  a              c   c   c   c   c              d   d    d   d   d
 
   此时s b c d都已经放好了,我们用了3个字节
   假如我们不浪费的话只要2个字节就够了
   那么我们来测试一下
*/
//struct S
//{
//    char a : 3;
//    char b : 4;
//    char c : 5;
//    char d : 4;
//};
//int main()
//{
//    struct S s;
//    printf("%zd\n", sizeof(struct S));//3
//    return 0;
//}
 
 
/*
这个结果和我们判断的是一样的,占了3个字节大小的空间
 
可事实真的是这样的么?
那么我们就再举个例子进行判断
*/
struct S
{
    char a : 3;
    char b : 4;
    char c : 5;
    char d : 4;
};
int main()
{
    struct S s = {0};//将每个比特位都设置为0
    s.a = 10;
    s.b = 12;
    s.c = 3;
    s.d = 4;
 
    printf("%zd\n", sizeof(struct S));
    return 0;
}
 
/*
//初始化的情况如下
1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24-----比特位
0  0  0  0  0  0  0  0  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
 
0  b  b  b  b  a  a  a  0   0   0   c   c   c   c   c   0   0   0   0   d   d   d   d
*/
/*
s.a = 10;
往a里面放10,,10的二进制序列就是1010,可是a只有3个比特位,这里的10是4个比特位,3个比特位放不下1010
那么我们只能从地位到高位进行存放,存的是010
 
s.b = 12;
往b里面放12,12的二进制位是1100,b是4个比特位,那么刚好放得下1100
 
s.c = 3;
往c里面放3,c占5个比特位,3的二进制是11,那么我们就将00011放进去
前三个比特位还是0
 
s.d = 4;
往d里面放4,4的二进制是100,d占4个比特位,那么我们就将0100放进去,第一个
 
1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24-----比特位
0  0  0  0  0  0  0  0  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
 
0  b  b  b  b  a  a  a  0   0   0   c   c   c   c   c   0   0   0   0   d   d   d   d
 
0  1  1  0  0  0  1  0  0   0   0   0   0   0   1   1   0   0   0   0   0   1   0   0
放置结果如上:
 
因为4个二进制位写一个16进制,那么我们将16进制表示出来
 
6     2     0     3       0       4
 
我们进行调试,和我们分析的是一模一样的
*/
/*总结:
在当前的vs环境下,开辟空间是从右向左使用,如果剩下的空间不够,那我们就浪费这些空间,再开辟一个字节
*/
 
 
 
 
/*
我们再将一开始的例子拿过来进行判断下
struct A
{
 int _a:2;
 int _b:5;
 int _c:10;
 int _d:30;
};
 
因为类型是int
那么我们开辟4个字节,23个比特位,但是a只要2个比特位,剩下30个比特位,
b用5个,还有25个比特位
c用10个,还有15个比特位
 
d说要用30个比特位,剩下的15个不够了
那么我们再开辟4个字节,就是32个比特位
那么我们给d用30个比特位,剩下2个
 
算下来我们总共开辟了8个字节,浪费了17个比特位
 
 
这就是我们之前为什么算出来是8个比特位了
 
 
*/

1.给定了空间后,在空间内部是从右向左使用

2.当剩下的空间不足以存放喜爱一个成员的时候,空间是浪费的

上面两种是不确定的,需要我们实时进行探究

位段的跨平台问题

  1. int 位段被当成有符号数还是⽆符号数是不确定的。
  2. 位段中最⼤位的数⽬不能确定。(16位机器最⼤16,32位机器最⼤32,写成27,在16位机器会

出问题。

  1. 位段中的成员在内存中从左向右分配,还是从右向左分配,标准尚未定义。
  2. 当⼀个结构包含两个位段,第⼆个位段成员⽐较⼤,⽆法容纳于第⼀个位段剩余的位时,是舍弃

剩余的位还是利⽤,这是不确定的。

总结:

跟结构相⽐,位段可以达到同样的效果,并且可以很好的节省空间,但是有跨平台的问题存在。

位段的注意事项

位段的⼏个成员共有同⼀个字节,这样有些成员的起始位置并不是某个字节的起始位置,那么这些位

置处是没有地址的。内存中每个字节分配⼀个地址,⼀个字节内部的bit位是没有地址的。

所以不能对位段的成员使⽤&操作符,这样就不能使⽤scanf直接给位段的成员输⼊值,只能是先输⼊

放在⼀个变量中,然后赋值给位段的成员。

struct A
{
    int _a : 2;
    int _b : 5;
    int _c : 10;
    int _d : 30;
};
int main()
{
    struct A sa = { 0 };
    //scanf("%d", &sa._b);//这是错误的
 
    //正确的⽰范
    int b = 0;
    scanf("%d", &b);
    sa._b = b;//直接进行赋值
    return 0;
}
相关文章
|
18天前
|
存储 C语言
C语言程序设计核心详解 第九章 结构体与链表概要详解
本文档详细介绍了C语言中的结构体与链表。首先,讲解了结构体的定义、初始化及使用方法,并演示了如何通过不同方式定义结构体变量。接着,介绍了指向结构体的指针及其应用,包括结构体变量和结构体数组的指针操作。随后,概述了链表的概念与定义,解释了链表的基本操作如动态分配、插入和删除。最后,简述了共用体类型及其变量定义与引用方法。通过本文档,读者可以全面了解结构体与链表的基础知识及实际应用技巧。
|
24天前
|
C语言
c语言中的结构体
本文档详细介绍了C语言中结构体的使用方法,包括结构体的基本定义、变量声明与赋值、数组与指针的应用,以及结构体嵌套、与`typedef`结合使用等内容。通过示例代码展示了如何操作结构体成员,并解释了内存对齐的概念。
|
30天前
|
C语言
C语言结构体赋值的四种方式
本文总结了C语言结构体的四种赋值方式,并通过示例代码和编译运行结果展示了每种方式的特点和效果。
46 6
|
1月前
|
编译器 程序员 Linux
【C语言篇】结构体和位段详细介绍
跟结构相⽐,位段可以达到同样的效果,并且可以很好的节省空间,但是有跨平台的问题存在。
|
1月前
|
存储 编译器 C语言
【C语言篇】自定义类型:联合体和枚举详细介绍
像结构体⼀样,联合体也是由⼀个或者多个成员构成,这些成员可以不同的类型。
|
1月前
|
存储 安全 编译器
C语言自定义类型
C语言自定义类型
29 10
|
1月前
|
存储 C语言
C语言------结构体和共用体
这篇文章是关于C语言中结构体和共用体的实训,通过示例代码演示了结构体的定义、赋值、使用,以及如何使用结构体变量进行数据的组织和操作,包括输入、排序、求平均分和查找学生信息等功能。
C语言------结构体和共用体
|
3月前
|
网络协议 编译器 Linux
结构体(C语言)
结构体(C语言)
|
2月前
|
存储 编译器 定位技术
结构体数组在C语言中的应用与优化策略
结构体数组在C语言中的应用与优化策略
|
2月前
|
存储 编译器 数据库
结构体数组在C语言中的应用与优化技巧
结构体数组在C语言中的应用与优化技巧