我正在上一门关于操作系统的大学课程,我们正在学习如何将二进制转换为十六进制,十进制转换为十六进制等,今天我们刚刚学习了如何使用两个数字的补数(~number + 1)将有符号/无符号数字存储在内存中。

我们有几个练习要在纸上做,我希望在把我的工作交给老师之前能够验证我的答案。我为前几个练习写了一个c++程序,但现在我被困在如何用以下问题验证我的答案:

char a, b;

short c;
a = -58;
c = -315;

b = a >> 3;

我们需要在内存中给出a b c的二进制表示。

我已经在纸上做过了,它给了我以下结果(所有的二进制表示在内存的数字之后的二补):

A = 00111010(它是一个char,所以是1字节) B = 00001000(它是一个char,所以是1字节) C = 11111110 11000101(它是短的,所以是2字节)

有办法证实我的答案吗?在c++中是否有一种标准的方法来显示一个数字在内存中的二进制表示,或者我必须自己编写每一步(计算两者的补数,然后转换为二进制)?我知道后者不会花很长时间,但我很好奇是否有一个标准的方法来做到这一点。


当前回答

可重用的功能:

template<typename T>
static std::string toBinaryString(const T& x)
{
    std::stringstream ss;
    ss << std::bitset<sizeof(T) * 8>(x);
    return ss.str();
}

用法:

int main(){
  uint16_t x=8;
  std::cout << toBinaryString(x);
}

这适用于所有的整数。

其他回答

在c++ 20中,你可以使用std::format来做到这一点:

unsigned char a = -58;
std::cout << std::format("{:b}", a);

输出:

11000110

在旧的系统上,你可以使用{fmt}库,std::format是基于这个库的。{fmt}还提供了print函数,使这更容易和更有效(godbolt):

unsigned char a = -58;
fmt::print("{:b}", a);

免责声明:我是{fmt}和c++ 20 std::format的作者。

类似于已经发布的内容,只是使用位移位和掩码来获得位;适用于任何类型,作为一个模板(只是不确定是否有一个标准的方法来获得1字节中的比特数,我在这里使用8)。

#include<iostream>
#include <climits>

template<typename T>
void printBin(const T& t){
    size_t nBytes=sizeof(T);
    char* rawPtr((char*)(&t));
    for(size_t byte=0; byte<nBytes; byte++){
        for(size_t bit=0; bit<CHAR_BIT; bit++){
            std::cout<<(((rawPtr[byte])>>bit)&1);
        }
    }
    std::cout<<std::endl;
};

int main(void){
    for(int i=0; i<50; i++){
        std::cout<<i<<": ";
        printBin(i);
    }
}

我在玩在线编码游戏时就遇到过这个问题。这里有一个快速实现且相当直观的解决方案。它还避免输出前导零或依赖<bitset>

std::string s;
do {
    s = std::to_string(r & 1) + s;
} while ( r>>=1 );

std::cout << s;

但是您应该注意,这个解决方案将增加您的运行时间,所以如果您正在竞争优化或根本不竞争,您应该使用本页上的其他解决方案之一。

这就是你要找的吗?

std::cout << std::hex << val << std::endl;

在c++中是否有一种标准的方法来显示内存中数字[…]的二进制表示?

不。没有std::bin,像std::hex或std::dec,但是你自己输出一个数字二进制并不难:

你输出最左边的位,通过屏蔽所有其他的位,左移,并对所有的位重复这一步骤。

(类型的比特数是sizeof(T) * CHAR_BIT。)