0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何使用位操作符实现低级别的位掩码

科技绿洲 来源:Java技术指北 作者:Java技术指北 2023-10-07 16:52 次阅读

在本文中,我们来看看如何使用位操作符实现低级别的位掩码。我们将看到我们如何将一个单一的int变量作为一个单独的数据容器。

位掩码

位掩码允许我们在一个数字变量中存储多个值。我们不再把这个变量看作一个整数,而是把它的每一个比特当作一个独立的值。

因为一个比特可以等于 0 或 1,我们也可以把它看成是 false 或 true 。我们也可以把一组比特切开,把它们当作一个较小的数字变量甚至是一个String

举个例子

假设我们有一个最小的内存空间,并且需要在一个int变量中存储所有关于用户账户的信息。前八位(来自32个可用位)将存储boolean信息,如 "该账户是否激活?"或 "该账户是否溢价?"

至于剩下的24位,我们将把它们转换成三个字符,作为用户的标识符。

编码

我们的用户将有一个标识符 "AAA",他将有一个活跃的高级账户(存储在前两个比特)。在二进制表示中,它将看起来像。

String stringRepresentation = "01000001010000010100000100000011";

使用内置的Integer#parseUnsignedInt方法,可以很容易地将其编码为一个int变量。

int intRepresentation = Integer.parseUnsignedInt(stringRepresentation, 2);
assertEquals(intRepresentation, 1094795523);

解码

这个过程也可以用 Integer#toBinaryString 方法来反转。

String binaryString = Integer.toBinaryString(intRepresentation);
String stringRepresentation = padWithZeros(binaryString);
assertEquals(stringRepresentation, "01000001010000010100000100000011");

提取一个比特

第一比特

如果我们想检查我们账户变量的第一位,我们只需要使用顺位 and 运算符和数字 1 作为掩码。因为数字 1在二进制形式中只有第一位被设置为1,其余的都是0,它将从我们的变量中删除所有的位,只留下第一个完整的位。

10000010100000101000001000000011
00000000000000000000000000000001
-------------------------------- &
00000000000000000000000000000001

然后我们需要检查产生的值是否不等于零。

intRepresentation & 1 != 0

任意位置的位

如果我们想检查其他的位,我们需要创建一个适当的掩码,这个掩码需要在给定的位置上有一个位设置为1,其余的设置为0。最简单的方法是对我们已有的掩码进行移位。

1 < < (position - 1)

上面这行代码的位置变量设置为3,将把我们的掩码从 00000000000000000000000000000001 变成

00000000000000000000000000000100

因此,现在,比特方程将看起来像这样。

10000010100000101000001000000011
00000000000000000000000000000100
-------------------------------- &
00000000000000000000000000000000

把所有这些放在一起,我们可以写一个方法来提取给定位置上的单个比特。

private boolean extractValueAtPosition(int intRepresentation, int position) {
    return ((intRepresentation) & (1 < < (position - 1))) != 0;
}

为了达到同样的效果,我们也可以将intRepresentation变量向相反方向移动,而不是改变掩码。

提取多个比特

我们可以用类似的方法从一个整数中提取多个比特。让我们提取我们的用户帐户变量的最后三个字节,并将其转换为一个字符串。首先,我们需要通过将变量向右移动来摆脱前八位的影响。

int lastThreeBites = intRepresentation > > 8;
String stringRepresentation = getStringRepresentation(lastThreeBites);
assertEquals(stringRepresentation, "00000000010000010100000101000001");

我们仍然有32位,因为int总是有32位。然而,现在我们只对前24位感兴趣,其余的都是零,会很容易被忽略。我们创建的int变量可以很容易地用作整数ID,但是因为我们想有一个字符串ID,所以我们还有一个步骤要做。

我们将把二进制的字符串表示法分成8个字符的组,把它们解析成char变量,然后把它们连接成一个最终的String

为了方便起见,我们还将忽略空字节。

Arrays.stream(stringRepresentation.split("(?<=G.{8})"))
  .filter(eightBits - > !eightBits.equals("00000000"))
  .map(eightBits - > (char)Integer.parseInt(eightBits, 2))
  .collect(StringBuilder::new, StringBuilder::append, StringBuilder::append)
  .toString();

应用一个比特掩码

我们也可以创建一个掩码来同时检查许多位,而不是提取和检查单个位的值。我们想检查我们的用户是否有一个活跃的高级账户,所以他的变量的前两个比特都设置为1。

我们可以用以前的方法分别检查它们,但创建一个掩码来选择它们,会更快。

int user = Integer.parseUnsignedInt("00000000010000010100000101000001", 2);
int mask = Integer.parseUnsignedInt("00000000000000000000000000000011", 2);
int masked = user & mask;

因为我们的用户有一个活跃的账户,但它不是高级账户,所以被屏蔽的值将只有第一个比特被设置为1。

assertEquals(getStringRepresentation(masked), "00000000000000000000000000000001");

现在,我们可以轻松而廉价地断言一个用户是否符合我们的条件。

assertFalse((user & mask) == mask);

总结

在本教程中,我们学习了如何使用位运算符来创建位掩码,并应用它们来从整数中提取二进制信息。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据
    +关注

    关注

    8

    文章

    6790

    浏览量

    88722
  • 二进制
    +关注

    关注

    2

    文章

    772

    浏览量

    41553
  • 内存
    +关注

    关注

    8

    文章

    2959

    浏览量

    73792
  • 运算符
    +关注

    关注

    0

    文章

    170

    浏览量

    11046
收藏 人收藏

    评论

    相关推荐

    Linux命令中“!”操作符的用法

    Linux中的'!'符号或操作符可以用作逻辑否定运算,也可以用于在历史记录中获取命令并进行修改或运行以前执行过的命令。
    发表于 07-05 10:07 1418次阅读

    MATLAB操作符和特殊字符

    MATLAB操作符和特殊字符* 矩阵乘法 .* 数组乘法 ^ 矩阵幂 .^ 数组幂 \ 左除或反斜杠 / 右除或斜杠 ./ 数组除 Kron Kronecker张量积 .. 父目录 … 继续
    发表于 09-22 16:05

    C语言,操作符优先级顺序。

    ;、==、!=) 〉逻辑运算(特别要说明,按与、或的优先级高于逻辑与、或),接下来就是三目运算?=然后是赋值操作符等号,最后是逗号,。运算
    发表于 01-16 17:30

    操作符的相关资料分享

    嵌入式C语言入门——操作符
    发表于 12-15 06:50

    操作C语言支持的几种操作符是哪些呢

    一、操作C语言支持的6种操作符如下:1.不改变其他的值的状况下,对某几个位进行设值。方法:先对需要设置的
    发表于 12-22 08:07

    操作符及其常用方式简要概述

    目录前言一、操作符及其常用方式二、实例应用解析(嵌入式笔试常考)前言操作在单片机的C语言开发中经常会用到,该操作主要用于读写寄存器,这篇
    发表于 02-17 06:33

    C语言编程二进制操作符

    C语言编程二进制操作符
    发表于 03-30 14:09 6次下载

    使用51单片机内核的汇编操作符笔记

    本文档的主要内容详细介绍的是使用51单片机内核的汇编操作符笔记。
    发表于 07-19 17:38 1次下载
    使用51单片机内核的汇编<b class='flag-5'>操作符</b>笔记

    C++:详谈取地址操作符重载

    取址操作符重载函数返回值为该类型的指针,无参数。
    的头像 发表于 06-29 11:59 3431次阅读
    C++:详谈取地址<b class='flag-5'>操作符</b>重载

    C++之操作重载学习的总结(二)

    复数的概念可以通过自定义类实现;复数中的运算操作可以通过操作符重载实现;赋值操作符只能通过成员函数实现
    的头像 发表于 12-24 16:26 553次阅读

    C++之操作符重载学习的总结

    操作符重载是c++的强大特性之一;操作符重载的本质是通过函数扩展操作符的功能;operator 关键字是实现操作符重载的关键。
    的头像 发表于 12-24 16:36 636次阅读

    C语言操作

    目录前言一、操作符及其常用方式二、实例应用解析(嵌入式笔试常考)前言 操作在单片机的C语言开发中经常会用到,该操作主要用于读写寄存器,
    发表于 12-22 19:09 12次下载
    C语言<b class='flag-5'>位</b><b class='flag-5'>操作</b>

    Verilog基础:几个常用的按操作符

    操作符是对二进制进行操作的运算
    的头像 发表于 11-09 10:57 1263次阅读

    Verilog基础:介绍几个常用的按操作符

    操作符是对二进制进行操作的运算。以下是一些常用的操作
    的头像 发表于 11-09 10:59 1589次阅读

    “+”操作符的使用技巧

    这篇写个平时易被忽略的小知识点,一元 + 操作符的使用技巧。
    的头像 发表于 12-28 13:27 488次阅读