网站首页 > 资源文章 正文
我们知道,C++中的基本数据类型是按字节(byte,8个位bit组成一个字节byte)来存储的,从1-16个字节不等。
但对于一些非此即彼的逻辑值(或真或假,true (1) or false (0),这样的值称为标志类型值,flag),是否可以用一个位(本身就是一个开关逻辑值)来存储呢?答案是可以的,C++提供了有两种访问位的方法(按位运算符和在结构中创建位字段),将一个字节掰开用。
一、使用按位运算符来访问位
位运算在编程硬件设备中非常有用,因为设备的状态经常表示为一系列单独的标志(也就是字节的每个位可以表示设备各个方面的状态),在需要把一组一关标志装入单个变量中时,按位运算符也非常有用。
假设程序中有一个输入字段,“你有护照吗?”答案将是真(1)或假(0)。
定义一个flags变量:
unsigned char flags=0;
固定不同值的位位置(从0到7计数),这里我们将存储3个不同的值。
bit 0) Marital status bit 1) Passport status bit 2) Disability status flags |= 0x01; //set bit 0 flags |= 0x02; //set bit 1 flags |= 0x04; //set bit 2
现在就可以通过位运算来进行判断:
if(flags & 0x01) printf("Marital status: true\n"); else printf("Marital status: false\n"); if(flags & 0x02) printf("Passport status: true\n"); else printf("Passport status: false\n"); if(flags & 0x04) printf("Disability status: true\n"); else printf("Disability status: false\n");
如何清除特定的一个位?
flags &= ~0x02; //passport status==false
如何清除全部位?
flags =0;
用于检查特定位的值:
bit 0 0x01 bit 1 0x02 bit 2 0x04 bit 3 0x08 bit 4 0x10 bit 5 0x20 bit 6 0x40 bit 7 0x80
完整代码附后。
其它的一些应用场景:
1使用按位与&运算来判断奇偶数
奇偶数判断我们可以使用%运算符,其实还有个更简单高效的办法,我们的整数,在计算机中存储的都是二进制,奇数的最后一位必是1,所以我们可以这样写:
#include <stdio.h> int main() { int number; printf("请输入一个整数: "); scanf("%d", &number); // 判断这个数最后一位是1这为奇数 if(number&1) printf("%d 是奇数。", number); else printf("%d 是偶数。", number); return 0; }
2 使用按位取反运算符求unsigned int的最大值
unsigned int imax=0; imax = ~imax; cout<<imax; //4294967295 cout<<hex<<imax; //ffffffff int imax2 = -1; cout<<dec<<(unsigned int)imax2; //4294967295 //<limits.h>有定义LONG_MAX //2147483647
3 窗口样式选项组合
窗口样式选项通过将32位字中独特的某个位设置为1来定义,可以使用按位或运算来组合。这些表示某种特定样式的位通常称为标志。
wc.style = CS_HREDRAW | CS_VREDRAW; // CS_HREDRAW是宏定义 // 位运算组合常量,产生一个复合值来指定窗体风格
4 年份的属性组合
如用一个int lunarInfo = 0x0a974(0000 1010 0 1001 0111 0100)来表示1982年的数据:
表示1982年的4月为闰月,即有第二个4月,且是闰小月。从1月到13月的天数依次为:30、29、30、29、29(闰月)、 30、29、29、30、 29、30、30、30。
二、在结构中创建位字段来访问位
如果程序的结构中包含多个开关量,只有 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
在结构内声明位域的形式如下:
struct { type [member_name] : width ; };
下面是有关位域中变量元素的描述:
元素描述type整数类型,决定了如何解释位域的值。类型可以是整型、有符号整型、无符号整型。member_name位域的名称。width位域中位的数量。宽度必须小于或等于指定类型的位宽度。
带有预定义宽度的变量被称为位域。位域可以存储多于 1 位的数,例如,需要一个变量来存储从 0 到 7 的值,您可以定义一个宽度为 3 位的位域,如下:
struct { unsigned int age : 3; } Age;
上面的结构定义指示 C 编译器,age 变量将只使用 3 位来存储这个值,如果您试图使用超过 3 位,则无法完成。让我们来看下面的实例:
#include <stdio.h> #include <string.h> struct { unsigned int age : 3; } Age; int main( ) { Age.age = 4; printf( "Sizeof( Age ) : %d\n", sizeof(Age) ); printf( "Age.age : %d\n", Age.age ); Age.age = 7; printf( "Age.age : %d\n", Age.age ); Age.age = 8; // 二进制表示为 1000 有四位,超出 printf( "Age.age : %d\n", Age.age ); return 0; }
当上面的代码被编译时,它会带有警告,当上面的代码被执行时,它会产生下列结果:
Sizeof( Age ) : 4 Age.age : 4 Age.age : 7 Age.age : 0
附:
#include <stdio.h> #include <stdlib.h> int main() { unsigned char flags=0; flags |=0x01; flags |=0x02; flags |=0x04; if(flags & 0x01) printf("Marital status: true\n"); else printf("Marital status: false\n"); if(flags & 0x02) printf("Passport status: true\n"); else printf("Passport status: false\n"); if(flags & 0x04) printf("Disability status: true\n"); else printf("Disability status: false\n"); flags &= ~0x02; if(flags & 0x01) printf("Marital status: true\n"); else printf("Marital status: false\n"); if(flags & 0x02) printf("Passport status: true\n"); else printf("Passport status: false\n"); if(flags & 0x04) printf("Disability status: true\n"); else printf("Disability status: false\n"); system("pause"); return 0; } /* Output Marital status: true Passport status: true Disability status: true Marital status: true Passport status: false Disability status: true */
-End-
- 上一篇: 西门子LOGO常见问题解答,你用过LOGO吗?
- 下一篇: 这就是为什么写程序要用常通标志位的真正原因
猜你喜欢
- 2024-09-27 侧方位停车技巧,可以这样修正方向一把入库
- 2024-09-27 把PLC程序一步步讲明白了,那么PLC编程还会很难嘛?
- 2024-09-27 食品生产日期怎么标示?(食品生产日期怎么写)
- 2024-09-27 为什么CAN一致性测试中这几项如此重要?
- 2024-09-27 漫威6位超级英雄的独有标志,最后一个漫威粉也猜不出来!
- 2024-09-27 IP地址、子网掩码、及ip段-如192.168.0.1/24是什么意思?
- 2024-09-27 美式橄榄球球场的每条线的名称和作用?
- 2024-09-27 老司机用心总结,汽车上按钮图解,收藏起来随时看
- 2024-09-27 形位公差符号:掌握精度,铸就精工制造品质
- 2024-09-27 机械:产品形、位公差及符号分类图解,看公差图不求人
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- 电脑显示器花屏 (79)
- 403 forbidden (65)
- linux怎么查看系统版本 (54)
- 补码运算 (63)
- 缓存服务器 (61)
- 定时重启 (59)
- plsql developer (73)
- 对话框打开时命令无法执行 (61)
- excel数据透视表 (72)
- oracle认证 (56)
- 网页不能复制 (84)
- photoshop外挂滤镜 (58)
- 网页无法复制粘贴 (55)
- vmware workstation 7 1 3 (78)
- jdk 64位下载 (65)
- phpstudy 2013 (66)
- 卡通形象生成 (55)
- psd模板免费下载 (67)
- shift (58)
- localhost打不开 (58)
- 检测代理服务器设置 (55)
- frequency (66)
- indesign教程 (55)
- 运行命令大全 (61)
- ping exe (64)
本文暂时没有评论,来添加一个吧(●'◡'●)