位域

如果程序的结构中包含多个开关量,只有 TRUE/FALSE 变量,如下:

struct
{unsigned int widthValidated;unsigned int heightValidated;
} status;

这种结构需要 8 字节的内存空间,但在实际上,在每个变量中,我们只存储 0 或 1。在这种情况下,C 语言提供了一种更好的利用内存空间的方式。如果您在结构内使用这样的变量,您可以定义变量的宽度来告诉编译器,您将只使用这些字节。例如,上面的结构可以重写成:

struct
{unsigned int widthValidated : 1;unsigned int heightValidated : 1;
} status;

现在,上面的结构中,status 变量将占用 4 个字节的内存空间,但是只有 2 位被用来存储值。如果您用了 32 个变量,每一个变量宽度为 1 位,那么 status 结构将使用 4 个字节,但只要您再多用一个变量,如果使用了 33 个变量,那么它将分配内存的下一段来存储第 33 个变量,这个时候就开始使用 8 个字节。

实例:

#include <stdio.h>
#include <string.h>/* 定义简单的结构 */
struct
{unsigned int widthValidated;unsigned int heightValidated;
} status1;/* 定义位域结构 */
struct
{unsigned int widthValidated : 1;unsigned int heightValidated : 1;
} status2;int main( )
{printf( "Memory size occupied by status1 : %d\n", sizeof(status1));printf( "Memory size occupied by status2 : %d\n", sizeof(status2));return 0;
}

结果:

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

位域声明

有些信息在存储时,并不需要占用一个完整的字节,而只需占几个或一个二进制位。例如在存放一个开关量时,只有 0 和 1 两种状态,用 1 位二进位即可。为了节省存储空间,并使处理简便,C 语言又提供了一种数据结构,称为"位域"或"位段"。

所谓"位域"是把一个字节中的二进位划分为几个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。这样就可以把几个不同的对象用一个字节的二进制位域来表示。

典型的实例:

  • 用 1 位二进位存放一个开关量时,只有 0 和 1 两种状态。
  • 读取外部文件格式——可以读取非标准的文件格式。例如:9 位的整数。

位域的定义和位域变量的说明

定义:

struct 位域结构名
{位域列表};

位域列表:

type [member_name] : width ;
元素 描述
type 只能为 int(整型),unsigned int(无符号整型),signed int(有符号整型) 三种类型,决定了如何解释位域的值。
member_name 位域的名称。
width 位域中位的数量。宽度必须小于或等于指定类型的位宽度。

带有预定义宽度的变量被称为位域

对于位域定义的几点说明:

1.一个位域存储在同一个字节中,如一个字节所剩空间不够存放另一位域时,则会从下一单元起存放该位域。也可以有意使某位域从下一单元开始。例如:

struct bs{unsigned a:4;unsigned  :4;    /* 空域 */unsigned b:4;    /* 从下一单元开始存放 */unsigned c:4
}

在这个位域定义中,a 占第一字节的 4 位,后 4 位填 0 表示不使用,b 从第二字节开始,占用 4 位,c 占用 4 位。

2.位域的宽度不能超过它所依附的数据类型的长度,成员变量都是有类型的,这个类型限制了成员变量的最大长度,: 后面的数字不能超过这个长度。

3.位域可以是无名位域,这时它只用来作填充或调整位置。无名的位域是不能使用的。例如:

struct k{int a:1;int  :2;    /* 该 2 位不能使用 */int b:3;int c:2;
};

从以上分析可以看出,位域在本质上就是一种结构类型,不过其成员是按二进位分配的。

位域的使用

位域变量名.位域名
位域变量名->位域名

举例:

#include<stdio.h>int main() {struct bs {unsigned a : 1;unsigned b : 3;unsigned c : 4;} bit, * pbit;bit.a = 1;    /* 给位域赋值(应注意赋值不能超过该位域的允许范围) */bit.b = 7;    /* 给位域赋值(应注意赋值不能超过该位域的允许范围) */bit.c = 15;    /* 给位域赋值(应注意赋值不能超过该位域的允许范围) */printf("%d,%d,%d\n", bit.a, bit.b, bit.c);    /* 以整型量格式输出三个域的内容 */pbit = &bit;    /* 把位域变量 bit 的地址送给指针变量 pbit */pbit->a = 0;    /* 用指针方式给位域 a 重新赋值,赋为 0 */pbit->b &= 3;    /* 使用了复合的位运算符 "&=",相当于:pbit->b=pbit->b&3,位域 b 中原有值为 7,与 3 作按位与运算的结果为 3(111&011=011,十进制值为 3) */pbit->c |= 1;    /* 使用了复合位运算符"|=",相当于:pbit->c=pbit->c|1,其结果为 15 */printf("%d,%d,%d\n", pbit->a, pbit->b, pbit->c);    /* 用指针方式输出了这三个域的值 */
}

结果:

1,7,15
0,3,15

typedef

C 语言提供了 typedef 关键字,您可以使用它来为类型取一个新的名字。

按照惯例,定义时会大写字母,以便提醒用户类型名称是一个象征性的缩写,但您也可以使用小写字母。

举例:

typedef unsigned char BYTE;

在这个类型定义之后,标识符 BYTE 可作为类型 unsigned char 的缩写,

BYTE  b1, b2;unsigned char b1, b2;

您也可以使用 typedef 来为用户自定义的数据类型取一个新的名字。

举例:

#include <stdio.h>
#include <string.h>typedef struct Books
{char  title[50];char  author[50];char  subject[100];int   book_id;
} Book;int main()
{Book book;strcpy_s(book.title, 50, "C 教程");strcpy_s(book.author, 50, "Runoob");strcpy_s(book.subject, 100, "编程语言");book.book_id = 12345;printf("书标题 : %s\n", book.title);printf("书作者 : %s\n", book.author);printf("书类目 : %s\n", book.subject);printf("书 ID : %d\n", book.book_id);return 0;
}

结果:

书标题 : C 教程
书作者 : Runoob
书类目 : 编程语言
书 ID : 12345

typedef vs #define

#define 是 C 指令,用于为各种数据类型定义别名,与 typedef 类似,但是它们有以下几点不同:

  • typedef 仅限于为类型定义符号名称,#define 不仅可以为类型定义别名,也能为数值定义别名,比如您可以定义 1 为 ONE。
  • typedef 是由编译器执行解释的,#define 语句是由预编译器进行处理的。

强制类型转换

(type_name) expression

类型转换可以是隐式的,由编译器自动执行,也可以是显式的,通过使用强制类型转换运算符来指定。在编程时,有需要类型转换的时候都用上强制类型转换运算符,是一种良好的编程习惯。

整数提升

整数提升是指把小于 int 或 unsigned int 的整数类型转换为 int 或 unsigned int 的过程。

常用的算术转换

常用的算术转换是隐式地把值强制转换为相同的类型。编译器首先执行整数提升,如果操作数类型不同,则它们会被转换为下列层次中出现的最高层次的类型:

常用的算术转换不适用于赋值运算符、逻辑运算符 && 和 ||。

C语言九:位域(位域声明、位域的定义和位域变量的说明、对于位域定义的几点说明:、位域的使用)、typedef(typedef vs #define)、强制类型转换(整数提升、常用的算术转换)相关推荐

  1. C语言隐式/显式类型转换 | C++四种强制类型转换、类的隐式转换、explicit

    文章目录 C语言类型转换 隐式类型转换 显式类型转换 C++ 强制类型转换 static_cast reinterpret_cast const_cast dynamic_cast 类的隐式类型转换 ...

  2. c语言字符串强制类型转换,C语言学习九 —头文件强制类型转换错误处理

    预处理器 C 预处理器不是编译器的组成部分,但是它是编译过程中一个单独的步骤.简言之,C 预处理器只不过是一个文本替换工具而已,它们会指示编译器在实际编译之前完成所需的预处理.我们将把 C 预处理器( ...

  3. C语言乘于强制转换哪个优先级高,C语言中关于强制类型转换问题

    因为朋友问到,因此整理了一份,若关于一些认识有错误还望指出......算法 ● 若是一个运算符两边的运算数类型不一样,先要将其转换为相同的类型,即较低类型转换为较高类型,而后再参加运算,转换规则以下图 ...

  4. 020 C语言基础:C语言强制类型转换与错误处理

    文章目录 一:概述 二:整数提升 三:常用的算术转换 四:错误处理 4.1:概述 4.2:errno/perror()/strerror() 一:概述 强制类型转换是把变量从一种类型转换为另一种数据类 ...

  5. 类的自动转换和强制类型转换

    类型转换 将一个标准类型变量的值赋值给另一种标准类型的变量时,如果这两种类型兼容,则C++自动将这个值转换为接收变量的类型. long count = 8; //int类型转换为long类型 doub ...

  6. C语言基础教程之强制类型转换

    C 强制类型转换 强制类型转换是把变量从一种类型转换为另一种数据类型.例如,如果您想存储一个 long 类型的值到一个简单的整型中,您需要把 long 类型强制转换为 int 类型.您可以使用强制类型 ...

  7. C语言中的强制类型转换

    强制类型转换是把变量从一种类型转换为另一种数据类型.例如,如果您想存储一个 long 类型的值到一个简单的整型中,您需要把 long 类型强制转换为 int 类型.您可以使用强制类型转换运算符来把值显 ...

  8. C语言基础:强制类型转换

    1. 强制类型转换 强制类型转换是把变量从一种类型转换为另一种数据类型. 语法: (type_name) expression 实例:使用强制类型转换运算符把一个整数变量除以另一个整数变量,得到一个浮 ...

  9. c语言强制转换为结构体,C语言结构体的强制类型转换

    陈浩师兄03年的一篇博客<用C写有面向对象特色的程序>描述了用C语言来实现相似C++类继承的方法,这样方法的核心要点就是结构体的强制类型转换,让我来简单分析分析C语言中的结构体强制类型转换 ...

最新文章

  1. github README.md教程
  2. 检验两组数据是否显著差异_SPSS非参数两个相关样本检验
  3. C# winform 捕获全局异常
  4. Maven系列--setting.xml 配置详解
  5. oracle_j000,Process J000 died, kkjcre1p: unable to spawn jobq slave process引起的宕机
  6. www.opensymphony.com - Class: java.net.PlainSocketImpl
  7. ASP.NET 2.0 中的 DataSource 系列控件
  8. 三维重建18: 图像深度获取
  9. mongo shell连接到mongoDB及shell提示符下执行js脚本
  10. WINCE Driver 心得总结
  11. 2007级计算机技术专科毕业设计,2007级计算机科学与技术本科毕业设计选题
  12. UIWebView控件的简易浏览器小案例
  13. sqlmap详细使用教程
  14. linux可以用什么c语言编译器,嵌入式Linux下最常用的C语言编译器GCC命令详解
  15. TTL转RS232电路设计
  16. 自己怎么制作地图,如何绘制电子版地图?
  17. html文字溢出怎样处理,css文本溢出处理
  18. 典型计算机控制的电子测试系统组成,LIV测试系统的结构组成和应用分析
  19. 求助:用Python获取百度云服务access_token总是失败
  20. 欢迎Edrp开发组第一个成员Zhuang Liu的加入!

热门文章

  1. HTML+CSS错题整理
  2. 阿里巴巴商家使用频率最多的数据接口分享
  3. 轻量级日志 Loki 全攻略
  4. html向下的箭头符号怎么打,向下的箭头怎么打
  5. InnoDB: space header page consists of zero bytes in tablespace ./mysql/iyikcr32.ibd (table mysql/iyi
  6. IOS 跳转导航地图
  7. 深圳东部公交WIFI试用体验
  8. win11 任务栏角溢出里的程序图标记录如何删除(WIN 缓存图标清理)
  9. ps磨皮插件专用智能磨皮插件 AI算法美颜 提高P图效率
  10. unsw计算机科学的挂科率,2020年新南威尔士大学研究生挂科率