赞
踩
单独操作变量中的位
发送字节控制硬件设备
与文件相关的操作系统信息、通过特定位表明特定项
压缩和加密操作直接处理位
二进制0、1:表示内存和寄存器中位的开闭状态
十进制:基于10的幂、2157:2* 103+1* 102+5* 101+7* 100
二进制:基于2的幂、1101:1* 23+1* 22 +0* 21+1* 20 =13(十进制)
字节:储存系统字符集所需大小、通常8位、可以是9位、16位或其他值
8位字节:描述存储器芯片和数据传输率
从左往右:高阶位->低阶位
8位字节最大值:11111111
128+64+32+16+8+4+2+1=255
最小值:00000000
1字节存储范围 0~255(unsigned char)或-128~+127(signed char) 共256个值
符号量表示:
最高阶位存储符号0正\1负,右7位表示数字
10000001表示-1
00000001表示1
表示范围 -127~+127
有+0和-0
二进制补码:
最高位为0、右7位表示数字、0~+127
最高位为1、右7位按位取反+1、-128~-1
11111111表示-1
1000000表示-128
二进制反码:
最高位为0、右7位表示数字、0~+127
最高位为1、右7位按位取反、-127~-0
11111110表示-1
11111111表示-0
十进制小数、0.527:5/10+2/100+7/1000
二进制小数、.101:1/2+0/4+1/8 =0.625(十进制)
二进制小数+二进制指数
0-7表示数字、基于8的幂:451->4 * 82+5 * 81+1 * 80=297(十进制)
每个8进制位对应3个2进制位:0377->011111111
转换时可以去掉最高位的0、不可以去掉中间和低位0
缺点:用3倍的二进制数表示
在C语言中八进制前面加0:0451
0-9、A-F表示0-15、基于16的幂:A3F->10* 162+3* 161+15*160=2623(十进制)
每个16进制对应4个2进制数
1字节对应2个16进制、前4位和后4位
在C语言中十六进制前面加0x、字母大小写不分:0xa3f、0xA3F
用于整型数据、针对每一个位进行
常规逻辑运算符(&&、|| 和! )操作的是整个值
一元运算符~:1->0、0->1
unsigned char val = 2; // 二进制 0000 0010
unsigned char newval = ~val; // 不会改变val的值val:2、返回新值、newval:253(1111 1101)
val = ~val; // 改变val的值
&:逐位比较2个运算对象、生成一个新值
对应位都为1时、结果为1、其他情况结果为0
1 0 0 1 0 0 1 1 &
0 0 1 1 1 1 0 1 =
0 0 0 1 0 0 0 1
掩码:设置为开1、关0的位组合、需要隐藏的位设置为0
#define MASK 00000010
unsigned char flag;
// 掩码
flag &= MASK;
/* &=运算符、相当于flag = flag & MASK;
&0=0 &1=保持不变、flag第二位保持不变、其他置0
用掩码中的0隐藏flag中的位、只有为1的位可见:用掩码覆盖在flags上 */
// ch &= 0xff; // 保持最后8位不变、其他位都设置为0、无论原值有多少位、结果设置为1个8位字节
关闭指定位
// 关闭位
flag &= ~MASK;
/* &=运算符、相当于 flag = flag & ~MASK;
~MASK:第二位为0、其他为1、11111101
&0=0 &1=保持不变、flag第二位置0、其他不变*/
检查某一位的值、不可以直接==(判断整体值)
// 检查位的值
if ((flag & MASK) == MASK)
/*00000010
&0=0 &1=保持不变、flag第二位保持不变、其他置0
再比较、只比较第二位
&优先级低于==,加括号
要注意掩码宽度至少和覆盖的值宽度相等*/
|:逐位比较2个运算对象、生成一个新值
对应位都为0时、结果为0、其他情况结果为1
1 0 0 1 0 0 1 1 |
0 0 1 1 1 1 0 1 =
1 0 1 1 1 1 1 1
打开特定值、其他值不变
// 打开位
flag |= MASK;
/* |=运算符、相当于 flag = flag | MASK; 00000010
|0=保持不变 |1=1、flag第二位置1、其他不变 */
^:逐位比较2个运算对象、生成一个新值
对应位不同时、结果为1、其他情况结果为0
1 0 0 1 0 0 1 1 ^
0 0 1 1 1 1 0 1 =
1 0 1 0 1 1 1 0
关闭已打开的位、打开已关闭的位
// 切换位
flag ^= MASK;
/* ^=运算符、相当于 flag = flag ^ MASK; 00000010
^0=保持不变 ^1=取相反、flag取第二位相反、其他不变*/
2进制的每一位同时移动
number << n、number 向左移动 n位、number*2n
左边溢出的值丢掉、右边空出的值填0
不改变运算对象
(1 0 0 0 1 0 1 0)<< 2
0 0 1 0 1 0 0 0
int stonk = 1;
int onkoo;
onkoo = stonk << 2; // 左移之后的值赋给新变量、原变量不变
stonk <<= 2; // stonk = stonk << 2; 左移并赋值
number >> n、number 向右移动 n位、number/2n(number>=0)
右边溢出的值丢掉、左边空出的值填0(无符号类型)或符号位(有符号类型部分机器)
不改变运算对象
无符号类型
(1 0 0 0 1 0 1 0) >>2
0 0 1 0 0 0 1 0
有符号类型
(1 0 0 0 1 0 1 0) >>2
0 0 1 0 0 0 1 0 在某些系统中的结果
1 1 1 0 0 0 1 0 在另些系统中的结果
#include <limits.h> //提供 CHAR_BIT的定义 char *itobs(int, char *); void show_bstr(const char *); int invert_end(int num, int bits); int sweet = 1; int ooosw; ooosw = sweet << 2; // 右移之后的值赋给新变量、原变量不变 sweet <<= 2; // sweet = sweet << 2; 左移并赋值 #define BYTE_MASK 0xff unsigned long color = 0x002a162f; unsigned char blue, green, red; red = color & BYTE_MASK; // 只取低8位 green = (color >> 8) & BYTE_MASK; // 取中间8位、将8位颜色移动至低字节、掩码把低字节赋给指定变量 blue = (color >> 16) & BYTE_MASK; // 取高8位 /* binbit.c --使用位操作显示二进制*/ char bin_str[CHAR_BIT * sizeof(int) + 1]; /* CHAR_BIT表示每字节的位数 sizeof(int)返回int类型占字节数 CHAR_BIT * sizeof(int) int类型位数 +1 空字符*/ int number; puts("Enter integers and see them in binary."); puts("Non-numeric input terminates program. "); while (scanf("%d", &number) == 1) { itobs(number, bin_str); printf("%d is ", number); show_bstr(bin_str); putchar('\n'); number = invert_end(number, 4);//取反后4位 printf("Inverting the last 4 bits gives\n"); show_bstr(itobs(number, bin_str)); putchar('\n'); } puts("Bye ! "); 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) // i-- 数组下标 n>>=1 右移一位、循环处理n中新的最右端的值 ps[i] = (01 & n) + '0'; /* 01:八进制掩码 1&n 0x1&n 即001(二进制)&n、只保留n最后一位的值、0、1 +'0' 转换为字符'0'、'1' 结果放在数组倒数第二个元素开始*/ ps[size] = '\0'; // 最后一个元素用来放空字符 return ps; // 修改ps之后返回ps、字符串首地址可作为printf参数 } void show_bstr(const char *str) { /*4位一组显示二进制字符串*/ int i = 0; while (str[i]) /*不是一个空字符*/ { putchar(str[i]); if (++i % 4 == 0 && str[i]) putchar(' '); } } int invert_end(int num, int bits) {// 取反num的后bit位 ~num 取反num里的所有位 int mask = 0; // 所有位都为0 int bitval = 1; while (bits-- > 0) // 循环bits次,每次操作一位 { mask |= bitval; // bitval 1对应的位置设置为1 bitval <<= 1; } return num ^ mask; // 取反num的右bit位 }
signed int 或 unsigned int 类型变量中相邻的位
C99和C11新增_Bool类型的位字段
结构声明建立字段,给字段提供标签和宽度
内含字段的结构允许在一个存储单元存多个字段
unsigned int 位字段结构的基本布局单元、即使结构中只有一个1位字段的成员、结构大小=sizeof(unsigned int)
struct {// 通过结构声明建立、为每个字段提供标签和宽度 unsigned int autfd : 1; // 标签+宽度、只有一位、只能赋值为0、1 unsigned int bldfc : 1; unsigned int undln : 1; unsigned int itals : 1; } prnt; // prnt包含4个1位的字段、存储在1个int大小的内存单元、只使用了其中4位 prnt.itals = 0; // 结构成员运算符.单独给字段赋值 prnt.undln = 1; struct { unsigned int code1 : 2; unsigned int code2 : 2; unsigned int code3 : 8; /*总位数超过1个unsigned int大小时、用下一个unsigned int的存储位置 1个字段不会跨越2个unsigned int之间的边界、会自动移动跨界字段、保持边界对齐、前一个unsigned int会留下洞*/ } prcode; // 两个2位的字段和一个8位的 prcode.code1 = 0; prcode.code2 = 3; prcode.code3 = 102; // 字段赋值不可超过字段范围 struct { unsigned int fieldl : 1; unsigned int : 2; // 未命名字段宽度填充未命名的洞 unsigned int field2 : 1; unsigned int : 0; // 宽度为0的未命名字段使下一字段与下一个整数对齐 unsigned int field3 : 1; /*在stuff.field1和stuff.field2之间,有一个2位的空隙、 stuff.field3将储存在下一个unsigned int 中*/ } stuff;
/*fields.c-- 定义并使用字段 */ #include <stdbool.h> // c99定义了bool(_Bool别名)、true、false // 位字段符号常量 /*线的样式 3种样式 2个单位(共4种组合)表示*/ #define SOLID 0 #define DOTTED 1 #define DASHED 2 /*三原色*/ #define BLUE 4 #define GREEN 2 #define RED 1 /*混合色 共8种颜色 3个单位8种组合表示*/ #define BLACK 0 #define YELLOW (RED | GREEN) #define MAGENTA (RED | BLUE) #define CYAN (GREEN | BLUE) #define WHITE (RED | GREEN | BLUE) const char *colors[8] = {"black", "red", "green", "yellow", "blue", "magenta", "cyan", "white"}; struct box_props { unsigned int opaque : 1; // 或者bool(c99 以后、不兼容时bool占1字节、加字节对齐导致结构体从4字节变为8字节) 方框透明、不透明 unsigned int fill_color : 3; // 方框填充颜色 unsigned int : 4; unsigned int show_border : 1; // 或者bool(c99 以后) 边框可见、隐藏 unsigned int border_color : 3; // 边框颜色 unsigned int border_style : 2; // 边框样式 0,1,2 unsigned int : 2; }; /* 前8位方框属性、后8位边框属性、空隙用未命名字段填充、 共占用16位,在系统中占sizeof(unsigned int)位、4位*/ void show_settings(const struct box_props *pb); struct box_props box = {true, YELLOW, true, GREEN, DASHED}; /* 创建并初始化unsigned int大小的box_props结构 初始化字段结构与普通结构语法相同 */ printf("original box settings : \n"); show_settings(&box); box.opaque = false; // 位字段成员赋值、结构成员表示法 box.fill_color = WHITE; // 成员赋值、边框和填充颜色可以用相同的颜色值 box.border_color = MAGENTA; box.border_style = SOLID; printf("\nModified box settings : \n"); show_settings(&box); getchar(); 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]); /// 位字段成员做数组下标 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"); } }
联合中结构和变量:涉及到结构载入顺序、第1字段载入最高阶位还是最低阶位
/*按位方法中用到的符号常量*/ #define OPAQUE 0x1 // 0号位 #define FILL_BLUE 0x8 // 方框颜色的位置信息、3号位为1、#define FILL_BLUE 1<<3 编译时求值 #define FILL_GREEN 0x4 #define FILL_RED 0x2 #define FILL_MASK 0xE // 方框颜色掩码 #define BORDER 0x100 #define BORDER_BLUE 0x800 // 边框颜色的位置信息、11号位为1、位置不同不可以和方框颜色一起显示 #define BORDER_GREEN 0x400 #define BORDER_RED 0x200 #define BORDER_MASK 0xE00 // 边框颜色掩码 #define B_SOLID 0 // 边框样式位置信息 #define B_DOTTED 0x1000 #define B_DASHED 0x2000 #define STYLE_MASK 0x3000 // 边框样式掩码 /*枚举替代#define、可以不声明标记 enum { OPAQUE = 0x1, FILL_BLUE = 0x8, FILL_GREEN = 0x4, FILL_RED = 0x2, FILL_MASK = 0xE, BORDER = 0x100, BORDER_BLUE = 0x800, BORDER_GREEN = 0x400, BORDER_RED = 0x200, BORDER_MASK = 0xE00, B_DOTTED = 0x1000, B_DASHED = 0x2000, STYLE_MASK = 0x3000 };*/ union Views /*4字节的联合*/ {// 涉及到结构载入前16位和后16位的区别、unsigned short存在后16位 struct box_props st_view; // 数据看作结构、4字节、只有2字节有数据 unsigned short us_view; // 数据看作unsigned short类型的变量、2字节 }; void show_settings1(unsigned short); printf("sizeof(unsigned int):%d\nsizeof(bool):%d\nsizeof(unsigned short):%d\nsizeof(struct box_props):%d\nsizeof(union Views):%d\n", sizeof(unsigned int), sizeof(bool), sizeof(unsigned short), sizeof(struct box_props), sizeof(union Views)); /*创建views联合,并初始化initialize struct box view unsigned int变量存储*/ union Views view = {{true, YELLOW, true, GREEN, DASHED}}; // 参考联合初始化 char bin_str[CHAR_BIT * sizeof(unsigned int) + 1]; printf("\noriginal view settings : \n"); show_settings(&view.st_view); // 使用位字段box_props类型的结构 printf("\nView settings using unsigned int view : \n"); show_settings1(view.us_view); // 使用unsigned short类型的 printf("bits are %s\n", itobs(view.us_view, bin_str)); view.us_view &= ~FILL_MASK; /*把之前表示填充色的位清0 位运算符访问*/ view.us_view |= (FILL_BLUE | FILL_GREEN); /*重置填充色 */ view.us_view ^= OPAQUE; /*切换是否透明的位*/ view.us_view |= BORDER_RED; /*错误的方法、不清0直接设置会被原来的位影响*/ view.us_view &= ~STYLE_MASK; /*把样式的位清0*/ view.us_view |= B_DOTTED; /*把样式设置为点*/ printf("\nModified view settings : \n"); show_settings(&view.st_view); printf("\nView settings using unsigned int view : \n"); show_settings1(view.us_view); printf("bits are %s\n", itobs(view.us_view, bin_str)); getchar(); void show_settings1(unsigned short us) { printf("us is %d.\n", us); printf("box is %s.\n", (us & OPAQUE) == OPAQUE ? "opaque" : "transparent"); printf("The fill color is %s.\n", colors[(us >> 1) & 07]); 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]); // us >> 9把边框颜色右移至最右端(0-2号位)&111(2进制)、关闭其他位 }
对齐:安排对象在内存的位置
对齐值:2的非负整数次幂
_Alignas 指定变量对齐值,指定的对齐值不可以小于基本对齐值
_Alignof(类型); //获取对其要求
#include<stdalign.h>//alignas alignof 别名 #include <stdlib.h> //void *aligned_alloc(size_t alignment, size_t size); // align.c-- 使用_Alignof和_Alignas(c11) double dx;//8,地址可以整除8 char ca;//1 char cx; double dz; char cb; char _Alignas(double) cz; // 8 或者_Alignas(double) char cz; // float _Alignas(char) fz; // error指定对齐值不可小于默认对齐值 printf("char alignment : %zd\n", _Alignof(char));//获取对其要求 printf("double alignment : %zd\n", _Alignof(double)); printf("&dx : %p\n", &dx); printf("&ca : %p\n", &ca); printf("&cx : %p\n", &cx); printf("&dz : %p\n", &dz);// printf("&cb : %p\n", &cb);// 1 printf("&cz : %p\n", &cz);// 8
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。