在 C/C++ 中检查最低有效位 (LSB) 和最高有效位 (MSB) 的值

Posted

技术标签:

【中文标题】在 C/C++ 中检查最低有效位 (LSB) 和最高有效位 (MSB) 的值【英文标题】:Check value of least significant bit (LSB) and most significant bit (MSB) in C/C++ 【发布时间】:2011-10-02 15:08:21 【问题描述】:

我需要检查 C/C++ 中整数的最低有效位 (LSB) 和最高有效位 (MSB) 的值。我该怎么做?

【问题讨论】:

【参考方案1】:
//int value;
int LSB = value & 1;

或者 (理论上不可移植,但实际上可以 - 请参阅史蒂夫的评论)

//int value;
int LSB = value % 2;

详情: 第二个公式更简单。 % 运算符是余数运算符。一个数字的 LSB 为 1,如果它是奇数,否则为 0。所以我们检查除以2的余数。第一个公式的逻辑是这样的:二进制数1是这样的:

0000...0001

如果你将这个与任意数字进行二进制与,结果的所有位将是 0,除了最后一个,因为 0 AND 其他任何值都是 0。如果你的最后一个位,结果的最后一个位将为 1数字是 1,因为 1 & 1 == 11 & 0 == 0

This 是一个很好的按位运算教程。

HTH。

【讨论】:

@Kobie:你理解公式的逻辑还是我更详细的解释? IMO %2 很愚蠢,因为尽管它在实践中有效,但这仅仅是因为在实践中所有 C++ 实现都使用二进制补码表示负整数。理论上它不一定有效,因为理论上-1 可能有它的 LSB 清晰(一个补码)。如果测试是针对 last bit,则使用 bitwise 运算符,而不是本质上与位无关的取模运算符 :-) @Steve:公平点,这就是我将其列为替代方案的原因,但无论如何我都会编辑答案以使其更清晰 @Kobie:一个可能的解决方案是执行variable & 1,直到您可以右移variable。一种:for (;variable != 0; variable >> 1) ... 。最后一个LSB 值对应于MSB @Kerrek:哦,当然……那是一个无限循环:)【参考方案2】:

你可以这样做:

#include <iostream>

int main(int argc, char **argv)

    int a = 3;
    std::cout << (a & 1) << std::endl;
    return 0;

这样你AND你的变量与LSB,因为

3: 011
1: 001

以 3 位表示。所以是AND

AND
-----
0  0  | 0
0  1  | 0
1  0  | 0
1  1  | 1

您将能够知道 LSB 是否为 1。

编辑:找到 MSB。

首先阅读Endianess 文章以同意MSB 的含义。在以下几行中,我们假设使用大端符号来处理。

要找到MSB,在下面的sn-p 中,我们将重点应用右移,直到MSB 变为AND1。 考虑以下代码:

#include <iostream>
#include <limits.h>

int main(int argc, char **argv)

    unsigned int a = 128; // we want to find MSB of this 32-bit unsigned int
    int MSB = 0;   // this variable will represent the MSB we're looking for

    // sizeof(unsigned int) = 4 (in Bytes)
    // 1 Byte = 8 bits
    // So 4 Bytes are 4 * 8 = 32 bits
    // We have to perform a right shift 32 times to have the
    // MSB in the LSB position.
    for (int i = sizeof(unsigned int) * 8; i > 0; i--) 

        MSB = (a & 1); // in the last iteration this contains the MSB value

        a >>= 1; // perform the 1-bit right shift
    

    // this prints out '0', because the 32-bit representation of
    // unsigned int 128 is:
    // 00000000000000000000000010000000
    std::cout << "MSB: " << MSB << std::endl; 

    return 0;

如果您在循环之外打印MSB,您将得到0。 如果你改变a的值:

unsigned int a = UINT_MAX; // found in <limits.h>

MSB 将是 1,因为它的 32 位表示是:

UINT_MAX: 11111111111111111111111111111111

但是,如果您对有符号整数做同样的事情,事情就会有所不同。

#include <iostream>
#include <limits.h>

int main(int argc, char **argv)

    int a = -128; // we want to find MSB of this 32-bit unsigned int
    int MSB = 0; // this variable will represent the MSB we're looking for

    // sizeof(int) = 4 (in Bytes)
    // 1 Byte = 8 bits
    // So 4 Bytes are 4 * 8 = 32 bits
    // We have to perform a right shift 32 times to have the
    // MSB in the LSB position.
    for (int i = sizeof(int) * 8; i > 0; i--) 

        MSB = (a & 1); // in the last iteration this contains the MSB value

        a >>= 1; // perform the 1-bit right shift
    

    // this prints out '1', because the 32-bit representation of
    // int -128 is:
    // 10000000000000000000000010000000
    std::cout << "MSB: " << MSB << std::endl; 

    return 0;

正如我在下面的评论中所说,正整数MSB总是0,而负整数MSB总是1.

您可以检查 INT_MAX 32 位表示:

INT_MAX: 01111111111111111111111111111111

现在。为什么循环使用sizeof()? 如果你只是按照我在评论中写的那样循环:(抱歉评论中缺少=

for (; a != 0; a >>= 1)
    MSB = a & 1;

您将始终得到1,因为C++ 不会考虑高于最高1 的“零填充位”(因为您将a != 0 指定为退出语句)。例如对于 32 位整数,我们有:

int 7 : 00000000000000000000000000000111
                                     ^ this will be your fake MSB
                                       without considering the full size 
                                       of the variable.

int 16: 00000000000000000000000000010000
                                   ^ fake MSB

【讨论】:

MSBLSB 取决于架构。如果您使用大端表示法,MSB 是最左边的位。不是第一次遇到非零,也不是其他一切。使用大端表示法,有符号整数中的MSB 确定符号(0:正数,1:负数)。 LSB 确定数字是偶数还是奇数(0:偶数,1:奇数)。 @Kobie:我编辑了回复,包括一个关于 Endianess 的***链接。【参考方案3】:
int LSB = value & 1;
int MSB = value >> (sizeof(value)*8 - 1) & 1;

【讨论】:

移动有符号整数不是不可移植的吗? 我认为它会在大端系统上崩溃..但不要引用我的话【参考方案4】:

其他人已经提到了:

int LSB = value & 1;

获取最低有效位。但是有一种比上面提到的更欺骗的方法来获得 MSB。如果该值已经是有符号类型,只需执行以下操作:

int MSB = value < 0;

如果是无符号数量,则将其转换为相同大小的有符号类型,例如如果value 被声明为unsigned,那么:

int MSB = (int)value < 0;

是的,正式的,不可移植的,未定义的行为,无论如何。但是在我所知道的每一个二进制补码系统和每个编译器上,它都可以正常工作。毕竟,高位是符号位,所以如果带符号的形式为负,则 MSB 为 1,如果为非负,则 MSB 为 0。所以方便地,对负数的带符号测试相当于检索MSB。

【讨论】:

【参考方案5】:

LSB 很简单。只需 x 和 1。

MSSB 有点棘手,因为字节可能不是 8 位,sizeof(int) 可能不是 4,并且右侧可能有填充位。

还有,带符号的整数,是指MS值位的符号位吗?

如果您指的是符号位,那么生活很容易。只是 x

如果你的意思是最重要的值位,是完全可移植的。

 int answer  = 0;
 int rack = 1;
 int mask  = 1;

 while(rack < INT_MAX)
 
    rack << = 1;
    mask << = 1;
    rack |= 1; 
  

 return x & mask;

这是一种冗长的做法。现实中

x & (1

【讨论】:

以上是关于在 C/C++ 中检查最低有效位 (LSB) 和最高有效位 (MSB) 的值的主要内容,如果未能解决你的问题,请参考以下文章

LSB最低有效位隐写入门

LSB和MSB

语音隐写基于 LSB语音隐藏matlab源码

图像隐写基于LSB+DCT实现数字水印嵌入提取带攻击测试matlab源码含GUI

字节序相关问题简单总结,LSB与MSB

OpenCV使用LSB方法提取图像