迹忆客 专注技术分享

当前位置:主页 > 学无止境 > 编程语言 > C语言 >

C 中的位域

作者:迹忆客 最近更新:2023/03/28 浏览次数:

在本篇文章中,我们将学习 C 语言中的位域。

我们将从位域开始讨论。 接下来我们将讨论位域存储,接着是C语言中位域的语法。

最后,我们将看到一个具有不同数据类型的位域,以了解内部具有位域的结构所占用的最小和最大空间。


C 中的位域

编程中的位域是一种独特的数据结构,可以帮助程序员节省内存。 位字段允许将内存分配给位结构。

让我们考虑一个只有黑白两种颜色的纯黑白图像。 我们只需要存储两个值:01

考虑一个 100x100 的小图像,将屏幕与每个维度的数千个像素进行比较。 图像中将有一万个像素。

在标准数据类型中,你可以选择C语言的unsigned char数据类型,它只占用一个字节; 但是,要保存一张纯黑白图像,则需要 10000 字节的内存。

使用位字段,您可以在一个字节中保存八个像素(1 个字节中有 8 个位)。 这意味着您将需要大约 1250 个字节而不是 10000 个。

这只是一个例子; 这并不意味着您可以仅在图像的情况下节省空间。 在一些有数千名考生出现的考试中,您只需要一位来存储通过/未通过信息; 否则,选项是为每个候选者使用一个字节。


C 中的位域存储

考虑以下结构来开始对位域存储的讨论:

struct {
   unsigned char is_married;
   unsigned char is_graduated;
} status0;

这个结构需要两个字节的内存空间; 但是,我们必须在两个字段中存储 01。 让我们继续寻找一种更好的节省空间的方法。

我们将从语法到代码详细了解位域。

在 C 语言中,我们有一个特定的语法来告诉每个变量所需的位数:

struct{
  type [variable_name] : size ; // Size will be in bits
}

重要的是要注意此语法可用于结构。 在这里,类型是任何数据类型,如 intcharshortunsigned char 等。

您已经很清楚 C 语言中的合法变量名称。 冒号是语法的一部分,在变量名和大小之间是必需的,最后,大小是所需的位数。

接下来可能会让您感到惊讶的是结构的大小和位大小。 请参见以下代码:

#include <stdio.h>

struct {
   unsigned char is_married;
   unsigned char is_graduated;
} status0;

struct {
   unsigned char is_married:1;
   unsigned char is_graduated:1;
} status1;

int main( ) {
    printf( "Memory size occupied by status1 : %ld bytes\n", sizeof(status0));
    printf( "Memory size occupied by status1 : %ld  bytes\n", sizeof(status1));
   return 0;
}

输出是:

Memory size occupied by status1 : 2 bytes
Memory size occupied by status1 : 1 bytes

在输出中,第一个结构占用 2 个字节(即每个字段 1 个字节),这是非常合乎逻辑的。 但是,第二个输出占用 1 个字节; 您可能期望 2 个字节或位。

问题是,为什么是一个字节? 逻辑是数据类型将根据 C 语言的例程定义占用一个字节。

但是,以位为单位指定大小允许程序员声明另外 7 个字段,每个字段为 1 位。

对于 1 个字节,总位数应保持小于等于 8 位。 否则,将消耗 2 个字节的存储空间。

请参阅以下代码:

#include <stdio.h>

struct {
   unsigned char a:1;
   unsigned char b:7;
} status0;

struct {
   unsigned char a:1;
   unsigned char b:1;
   unsigned char c:1;
   unsigned char d:1;
   unsigned char e:1;
   unsigned char f:1;
   unsigned char g:1;
   unsigned char h:1;
} status1;

int main( ) {
    printf( "Memory size occupied by status1 : %ld\n", sizeof(status0));
    printf( "Memory size occupied by status1 : %ld\n", sizeof(status1));
   return 0;
}

输出结果如下:

Memory size occupied by status1 : 1
Memory size occupied by status1 : 1

让我们看下一个示例,其中位数增加了:

#include <stdio.h>

struct {
   unsigned char a:3;
   unsigned char b:7;
   unsigned char c:7;
} status0;

struct {
   unsigned char a:1;
   unsigned char b:1;
   unsigned char c:1;
   unsigned char d:1;
   unsigned char e:1;
   unsigned char f:1;
   unsigned char g:1;
   unsigned char h:1;
   unsigned char i:1;
   unsigned char j:1;
} status1;

int main( ) {
    printf( "Memory size occupied by status1 : %ld\n", sizeof(status0));
    printf( "Memory size occupied by status1 : %ld\n", sizeof(status1));
   return 0;
}

输出结果如下:

Memory size occupied by status1 : 3
Memory size occupied by status1 : 2

在第一个结构中,总位数为 3+7+7=17,大于16比特(2字节)。 因此,将消耗 3 个字节。

在第一行输出中也可以看到相同的内容。

在第二个结构中,我们有 10 个字段,每个字段为 1 位,这需要 10 位; 因此,它将消耗两个字节。 同样,第二行输出证实了这个概念。


C 中 short 数据类型的位域

人们可能会认为需要 unsigned char 才能使用位域。 我们也可以将位域与其他数据类型一起使用。

在这里,我们考虑使用 short 数据类型来演示并更好地掌握位域的概念。

考虑以下代码:

#include <stdio.h>

struct {
   unsigned short a:3;
} status0;

struct {
   unsigned short a:3;
   unsigned short b:9;
   unsigned short c:4;
} status1;

int main( ) {
    printf( "Memory size occupied by status1 : %ld\n", sizeof(status0));
    printf( "Memory size occupied by status1 : %ld\n", sizeof(status1));
   return 0;
}

输出结果如下:

Memory size occupied by status1 : 2
Memory size occupied by status1 : 2

在这两个结构中,消耗的内存都是 2 个字节,因为 short 需要 2 个字节。 因此,所需的最小内存为 2 个字节。

但是,多个字段可能总共消耗 16 位(如第二个结构中所示),大小将保持为 2 字节。

如果位数从 16 开始增加,接下来的两个字节的 short 数据类型将被自动覆盖,结果将消耗四个 4。

让我们看看下面的 C 程序:

#include <stdio.h>

struct {
   unsigned short a:6;
   unsigned short b:6;
   unsigned short c:7;
} status1;

int main( ) {
    printf( "Memory size occupied by status1 : %ld\n", sizeof(status1));
   return 0;
}

此处,总位数为 6+6+7=19,因此输出为:

Memory size occupied by status1 : 4

请注意 ,内存逐字节增加,因为 char 具有单字节存储; 而在 short 的情况下,内存增加了两个字节,因为根据定义,short 有两个字节的存储空间。


C 中具有多种数据类型的位域

现在,是时候讨论位域存储要求,以防结构具有两种或多种数据类型。 在这种情况下,所需的最小字节数是结构中最大数据类型所需的最大空间。

比如一个结构体有 shortchar 成员,最大的类型是short,需要2个字节; 整个结构至少需要两个字节。

int & short 的情况下,int 是最大的类型; 因此,整个结构需要 4 个字节。 让我们借助以下代码示例来演示这个概念:

#include <stdio.h>

struct {
   unsigned short a:6;
   unsigned int b:6;
} status1;

struct {
   unsigned long long a:6;
   unsigned int b:6;
   unsigned short c:6;
} status2;

int main( ) {
    printf( "Memory size occupied by status1 : %ld\n", sizeof(status1));
    printf( "Memory size occupied by status1 : %ld\n", sizeof(status2));
   return 0;
}

输出结果如下:

Memory size occupied by status1 : 4
Memory size occupied by status1 : 8

在第一个结构中,int 是最大的数据类型; 因此,第一行输出显示 4 字节结构大小。

在第二个结构中,long long 是主导类型,因此输出的第二行显示该结构的八个字节大小。

最后,在多个数据大小的情况下增量会很简单; 增量步长是等于最大类型结构中的字节数。

让我们看一下下面的代码以获得更好的理解:

#include <stdio.h>

struct {
   unsigned short a:6;
   unsigned int b:30;
   unsigned long long c:50;
} status1;

int main( ) {
    printf( "Memory size occupied by status1 : %ld\n", sizeof(status1));
   return 0;
}

该结构有 50+30+6=86 位,而 8 个字节有 64 位。 因此,此结构需要双倍空间,如下面的输出所示:

Memory size occupied by status1 : 16

我们需要 16 个字节,其中 id 8+8 个字节。


总结

如果我们在程序中使用多位字段,我们可以节省空间。 我们可以在声明时指定一个结构体成员变量的位数。

结构的最小大小是结构中最大数据类型所需的最大字节数。

如果单个或多个字段共同消耗的位数超过结构中最大类型的大小,则消耗的内存将是最大内存类型大小的倍数。

转载请发邮件至 1244347461@qq.com 进行申请,经作者同意之后,转载请以链接形式注明出处

本文地址:

相关文章

在 C 语言中使用 typedef enum

发布时间:2023/05/07 浏览次数:181 分类:C语言

本文介绍了如何在 C 语言中使用 typedef enum。使用 enum 在 C 语言中定义命名整数常量 enum 关键字定义了一种叫做枚举的特殊类型。

C 语言中的静态变量

发布时间:2023/05/07 浏览次数:151 分类:C语言

本文介绍了如何在 C 语言中使用静态变量。在 C 语言中使用 static 变量在函数调用之间保存变量值

C 语言中生成随机数

发布时间:2023/05/07 浏览次数:64 分类:C语言

本文演示了如何在 C 语言中生成随机数。使用 rand 和 srand 函数在 C 语言中生成随机数

C 语言中的 i++ 与++i

发布时间:2023/05/07 浏览次数:83 分类:C语言

本文演示了如何在 C 语言中使用前缀增量与后缀增量运算符。C 语言中++i 和 i++ 记号的主要区别

C 语言中获取当前工作目录

发布时间:2023/05/07 浏览次数:182 分类:C语言

本文演示了如何在 C 语言中获取当前工作目录。使用 getcwd 函数获取当前工作目录的方法

C 语言中的位掩码

发布时间:2023/05/07 浏览次数:126 分类:C语言

本文介绍了如何在 C 语言中使用位掩码。使用 struct 关键字在 C 语言中定义位掩码数据

C 语言中的排序函数

发布时间:2023/05/07 浏览次数:181 分类:C语言

本文演示了如何在 C 语言中使用标准库排序函数。使用 qsort 函数对 C 语言中的整数数组进行排序

C 语言中的 extern 关键字

发布时间:2023/05/07 浏览次数:114 分类:C语言

本文介绍了如何在 C 语言中使用 extern 关键字。C 语言中使用 extern 关键字来声明一个在其他文件中定义的变量

C 语言中的 #ifndef

发布时间:2023/05/07 浏览次数:186 分类:C语言

本文介绍了如何在 C 语言中使用 ifndef。在 C 语言中使用 ifndef 保护头文件不被多次包含 C 语言中的头文件用于定义同名源文件中实现的函数的接口。

扫一扫阅读全部技术教程

社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

最新推荐

教程更新

热门标签

扫码一下
查看教程更方便