<18> 位运算 & 位段

位运算
逻辑运算表
/**********************************************************************
逻辑运算表
A and 0 = 0 A xor 1 = npt A
A and 1 = A A xor A = 0
A or 0 = A A and not A = 0
A or 1 = 1 A or not A = 1
A xor B = C 优先级:not > and > or
C xor A = B
C xor B = A
**********************************************************************/
移位
左移:操作数的各位左移,低位补0,高位溢出,左移N位,相当于乘2的N次方 eg:5<<2 = 20
右移:有符号右移和无符号右移。
无符号右移最高位为 0(逻辑右移);
有符号右移高位补符号位(算术右移)。正数右移 N 位相当于除以 2 的 N 次方,负数除法不能直接右移,需要调整。
位运算应用场景
互换变量值
求绝对值(abs函数原理)
位段
在某些地方,为了节约内存,用4个位来控制增删改查权限
两种写法:
传统 C 写法(位运算控制)
位段(位域)
有时存储一个信息不必用一个或多个字节,例如,“真”或“假”用 0 或 1 表示,只需 1 位即可。C 语言允许在一个结构体中以位为单位来指定其成员所占内存长度,这种以位为单位的成员称为“位段”或称“位域”( bit field) 。利用位段能够用较少的位数存储数据。
基本语法:
位段的声明和结构体类似,但它的成员是一个或多个位的字段。这些不同长度的字段实际存自一个或多个整型变量中
声明:位段成员必须是整型(有符号无符号即可)在成员名 : 整数;整数规定了成员所占的位数。
缺点:不可移植。其内存分配与内存对齐的实现方式依赖于具体的机器和系统,在不同的平台可能有不同的结果,这导致了位段在本质上是不可移植的。
声明以及注释
PS:位段不能是静态类型,不能对其&取地址运算,因此不存在位段的指针,编译器也不支持位段的引用。
无名位段(占位作用)
如果位段的定义没有给出标识符名字,那么这个属于无名位段,无法被初始化,无名位段仅仅用于填充内存布局作用。
只有无名位段的位数可以是0,这样占0位的无名位段,用于强迫下一个位段在内存分配边界对齐。
无名位段应用场景:
为以后更新占位
涉及内部操作中间放一些临时值
隐藏一些控制位
位段显示
位段显示会按照定义的有无符号自动填充为整型,参与普通变量的运算或者传参。比如n.ADD取出来转为整型参与运算。
无符号高位填充0,有符号高位填充取决于当前位数的高位。
0位段
0位段放弃当前对齐后的所有空间,从下一个对齐单位开始,重新安排位。相当于中间的对齐空间是个无名位段。
附录一:

void ShowPers(int nPermissions)
{
//查询是否有某某权限.& 运算。0000 0100 & 0000 0100 != 0
if ((nPermissions & PER_EDT) != 0)
{
puts("可以修改");
}
if ((nPermissions & PER_ADD) != 0)
{
puts("可以增加");
}
if ((nPermissions & PER_DEL) != 0)
{
puts("可以删除");
}
if ((nPermissions & PER_QUE) != 0)
{
puts("可以查询");
}
}

int main()
{

//权限控制。为了节约内存,用4个位来控制增删改查权限
//两种写法:传统 C 写法(位运算控制)
/*
* low byte
* 0000 QEAD

  Q: 可以修改
  E: 可以查看
  A: 可以访问
  D: 可以读写

*/

if 01

int nPermissions = 0;


//Set Edit 
nPermissions = nPermissions | PER_EDT;
//Set Add
nPermissions = nPermissions | PER_QUE;
//Set 
//nPermissions = nPermissions | PER_EDT;


printf("*********************************************************************\r\n");
//取消编辑权限( & 它的编辑权限取反) 
// 0000 0100 取反:1111 1011
// 做& 运算,就可以那个位变为0
nPermissions = nPermissions & ~PER_EDT;

ShowPers(nPermissions);

return 0;

}
附录二:
struct tagPermissions
{
int add : 2;
int del : 1;
int edt : 16;
int que : 3;
}tagPer;

void ShowPers1(tagPermissions tagPer)
{
//查询是否有某某权限.& 运算。0000 0100 & 0000 0100 != 0
if (tagPer.edt)
{
puts("可以修改");
}
if (tagPer.add != 0)
{
puts("可以增加");
}
if (tagPer.del != 0)
{
puts("可以删除");
}
if (tagPer.que != 0)
{
puts("可以查询");
}
}

int main()
{
tagPer.add = 15;
tagPer.del = 15;
tagPer.edt = 15;
tagPer.que = 15;
ShowPers1(tagPer);

}

posted @   kksllss  阅读(1)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示