15章的15.4.2【 位字段和按位运算符】例题---详解

daima

// 例题.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <stdio.h>
#include <stdbool.h>
#include <limits.h>

/* 一、位字段符号常量 */
/* 边框线样式  */
#define SOLID 0
#define DOTTED 1
#define DASHED 2
/* 三原色 */
#define BLUE 4 //10进制下
#define GREEN 2
#define RED 1
/* 混合颜色 */
#define BLACK 0
#define YELLOW (RED | GREEN)
#define MAGENTA (RED | BLUE)//由红色位'或'上蓝色位组成 100 | 001 = 101
#define CYAN (GREEN | BLUE)
#define WHITE (RED | GREEN | BLUE)

/* 二、按位方法中用到的符号常量 */
#define OPAQUE 0x1//0号位 :0001 =》这个顺位1号位,二进制0号位,用来给【bool opaque】判断使用
#define FILL_BLUE 0x8 //3号位 :1000(也可以左移运算符 :1 << 3的形式)
#define FILL_GREEN 0x4 //2号位 :0100
#define FILL_RED 0x2 //1号位 :0010
#define FILL_MASK 0xE //1110 :用来表示填充色的位(方便对填充色全部取反使用)

#define BORDER 0x100 //8号位 :0001 0000 0000(作用同0号位)
#define BORDER_BLUE 0x800 //11号位 :1000 0000 0000
#define BORDER_GREEN 0x400 //10号位 :0100 0000 0000
#define BORDER_RED 0x200 //9号位 :0010 0000 0000
#define BORDER_MASK 0xE00 //控制9、10、11号位 :1110 0000 0000

#define B_SOLID 0 //“洞”的作用

#define B_DOTTED 0x1000 //12号位 :0001 0000 0000 0000
#define B_DASHED 0x2000 //13号位 :0010 0000 0000 0000
#define STYLE_MASK 0x3000 //控制12、13号位 :0011 0000 0000 0000

const char *colors[8] = { "black", "red", "green", "yellow",  "blue","magenta", "cyan", "white" };
 //从0 - 7 :表示8种颜色的字符

struct box_props {
	bool opaque : 1;
	unsigned int fill_color : 3; //【位字段】的形式表示8种颜色
	unsigned int : 4; //可以用未命名的字段宽度“填充”未命名的“洞”。
					  //使用一个宽度为4的未命名字段迫使下一个字段与下一个整数对齐
	bool show_border : 1;
	unsigned int border_color : 3;
	unsigned int border_style : 2;
	unsigned int : 2;
};

union Views/* 把数据看作结构或unsigned short类型的变量,一次只能使用一个 */
{
	struct box_props st_view;
	 //使用为字段的box_props类型的结构体
	unsigned short us_view;
	 //整形变量中的相邻位的位数,要i和结构体中的声明的位字段大小,匹配
};

void show_settings(const struct box_props *pb);
void show_settings1(unsigned short);
char *itobs(int n, char *pt);


int main(void)
{
	/*创建Views联合,并初始化initialize struct box view*/
	//联合体变量中对应的参数,都是上诉位字段结构体中的布尔bool和unsigned int变量对应的表现状态
	//5个表现状态
	union Views box = { {true,  YELLOW, true, GREEN, DASHED } };

	char bin_str[8 * sizeof(unsigned int) + 1];
	 //8 * sizeof(unsigned int) :表示int类型的位数为32位

	printf("Original box settings:\n");
	show_settings(&box.st_view);//函数功能实现,需要获取地址信息才行,
								//因此该处要对结构体变量采用取地址操作
	printf("\nBox settings using unsigned int view:\n");
	show_settings1(box.us_view);

	printf("bits are %s\n", itobs(box.us_view, bin_str));
	box.us_view &= ~FILL_MASK; /* 把表示填充色的位清0 */
	box.us_view |= (FILL_BLUE | FILL_GREEN); /* 重置填充色 1100*/
	box.us_view ^= OPAQUE; /* 切换是否透明的位 */
	box.us_view |= BORDER_RED;/* 错误的方法 */
	box.us_view &= ~STYLE_MASK; /* 把样式的位清0 */
	box.us_view |= B_DOTTED;/* 把样式设置为点 */

	printf("\nModified box settings:\n");
	show_settings(&box.st_view);
	printf("\nBox settings using unsigned int view:\n");
	show_settings1(box.us_view);
	printf("bits are %s\n", itobs(box.us_view, bin_str));
	 //itobs同15.3.8实例中的程序一个道理(另一个文章中)

	return 0;
}

//位字段
void show_settings(const struct box_props *pb)
{
	printf("Box is %s.\n", pb->opaque == true ? "opaque" : "transparent");
	printf("The fill color is %s.\n", colors[pb->fill_color]);
	 //位字段成员作数组下标使用,将索引作为数组下标了(十进制是0-7)
	printf("Border %s.\n", pb->show_border == true ? "shown" : "not shown");
	printf("The border color is %s.\n", colors[pb->border_color]);
	printf("The border style is ");
	switch (pb->border_style)
	{
	case SOLID:
		printf("solid.\n"); 
		break;
	case DOTTED: 
		printf("dotted.\n"); 
		break; 
	case DASHED: 
		printf("dashed.\n"); 
		break;
	default :
		printf("unknown type.\n");
	}
}

void show_settings1(unsigned short us)
{
	printf("box is %s.\n", (us & OPAQUE) == OPAQUE ? "opaque" : "transparent");
	printf("The fill color is %s.\n", colors[(us >> 1) & 07]);
	 //opaque所占的0位不管,fill color占1、2、3位1110->右移一位为0111
	 //与掩码07组合(0000...0000 0111),关闭除右端3位之外的所有位
	 //这样结果也在 0~7 的范围内,可以作为colors[]数组的索引(下标)使用
	printf("Border %s.\n",(us & BORDER) == BORDER ? "shown" : "not shown");
	printf("The border style is ");
	switch (us & STYLE_MASK)
	{
	case B_SOLID: printf("solid.\n"); break; 
	case B_DOTTED: printf("dotted.\n"); break; 
	case B_DASHED: printf("dashed.\n"); break; 
	default: printf("unknown type.\n");
	}
	printf("The border color is %s.\n", colors[(us >> 9) & 07]);
	 //同fill color 
}

char *itobs(int n, char *ps)
{
	int i;
	const static int size = CHAR_BIT * sizeof(int);
	//注意理解,数组在内存中以二进制存在
	for (i = size - 1; i >= 0; i--, n >>= 1)
	{
		ps[i] = (01 & n) + '0';

	}
	ps[size] = '\0';
	return ps;
}

图片结论

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

对其中小点的理解

1、洞

在这里插入图片描述
.
.
.

2、系统为什么一直是32位

在这里插入图片描述


.
.

3、border color中的us为什么要右移9位

在这里插入图片描述
.
.

4、fill color为什么从1位开始(二进制下)

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

扳手的海角

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值