如何打印(使用cout)数字存储在内存中的方式?

Jes*_*ond 194 c++ binary iostream representation std-bitset

我正在学习关于操作系统的大学课程,我们正在学习如何从二进制转换为十六进制,十进制到十六进制等等.今天我们刚刚学习了如何使用二进制补码(〜数字)将有符号/无符号数存储在内存中+ 1).

我们在纸上做了几个练习,我希望能够在向老师提交作业之前验证我的答案.我为前几个练习编写了一个C++程序,但现在我不知道如何通过以下问题验证我的答案:

char a, b;

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

b = a >> 3;
Run Code Online (Sandbox Code Playgroud)

我们需要在内存中显示二进制表示a,bc.

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

a = 00111010(它是一个字符,所以1个字节)

b = 00001000(它是一个字符,所以1个字节)

c = 11111110 11000101(它是一个短的,所以2个字节)

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

Jer*_*fin 385

最简单的方法可能是创建一个std::bitset表示值,然后将其传递给cout.

#include <bitset>
...

char a = -58;    
std::bitset<8> x(a);
std::cout << x << '\n';

short c = -315;
std::bitset<16> y(c);
std::cout << y << '\n';
Run Code Online (Sandbox Code Playgroud)

  • 啊,我一直忘记`std :: bitset`!"+ 1"来自我. (20认同)
  • @Jesse:`bitset`的构造函数参数被解释为无符号值,与二进制补码相同.严格地说,C++不保证二进制补码算法,并且在你的例子中`-58 >> 3`操作是未定义的. (12认同)
  • 请原谅我的无知,但这只会显示数字的二进制表示(例如8将是00001000)或其内存表示(例如,如何通过处理符号位并使用"二进制补码"来存储-8)? (2认同)

小智 97

使用即时转换std::bitset.没有临时变量,没有循环,没有函数,没有宏.

Live On Coliru

#include <iostream>
#include <bitset>

int main() {
    int a = -58, b = a>>3, c = -315;

    std::cout << "a = " << std::bitset<8>(a)  << std::endl;
    std::cout << "b = " << std::bitset<8>(b)  << std::endl;
    std::cout << "c = " << std::bitset<16>(c) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

打印:

a = 11000110
b = 11111000
c = 1111111011000101
Run Code Online (Sandbox Code Playgroud)

  • 请注意,不需要硬编码大小。例如打印`x`使用:`std :: cout &lt;&lt; std :: bitset &lt;8 * sizeof(x)&gt;(x)`。 (5认同)

vit*_*aut 28

在 C++20 中,您将能够使用它std::format来执行此操作:

unsigned char a = -58;
std::cout << std::format("{:b}", a);
Run Code Online (Sandbox Code Playgroud)

输出:

unsigned char a = -58;
std::cout << std::format("{:b}", a);
Run Code Online (Sandbox Code Playgroud)

在此期间,您可以使用的{} FMT库std::format是基于。{fmt} 还提供了print使这更容易和更高效的功能(Godbolt):

unsigned char a = -58;
fmt::print("{:b}", a);
Run Code Online (Sandbox Code Playgroud)

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

  • @rturrado `std::format` 在 Visual Studio 2019 中可用。您必须 `#include &lt;format&gt;` 并设置 `/std:c++latest`。 (3认同)

Cub*_*bbi 25

如果要显示任何对象的位表示,而不仅仅是整数,请记住首先将其重新解释为char数组,然后可以打印该数组的内容,如十六进制,甚至二进制(通过bitset):

#include <iostream>
#include <bitset>
#include <climits>

template<typename T>
void show_binrep(const T& a)
{
    const char* beg = reinterpret_cast<const char*>(&a);
    const char* end = beg + sizeof(a);
    while(beg != end)
        std::cout << std::bitset<CHAR_BIT>(*beg++) << ' ';
    std::cout << '\n';
}
int main()
{
    char a, b;
    short c;
    a = -58;
    c = -315;
    b = a >> 3;
    show_binrep(a);
    show_binrep(b);
    show_binrep(c);
    float f = 3.14;
    show_binrep(f);
}
Run Code Online (Sandbox Code Playgroud)

需要注意的是最常见的系统是小端,这样的输出show_binrep(c)没有的1111111 011000101你期望的,因为这不是它是如何存储在内存中.如果你正在寻找二进制的表示,那么一个简单的cout << bitset<16>(c)工作.


sbi*_*sbi 10

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

std::bin,没有,喜欢std::hex或者std::dec,但是自己输出一个二进制文件并不难:

您通过屏蔽所有其他位置输出最左边的位,左移,并为您拥有的所有位重复该位.

(类型中的位数是sizeof(T) * CHAR_BIT.)


eud*_*xos 7

与已发布的内容类似,只需使用位移和掩码来获取该位; 可用于任何类型,作为模板(只是不确定是否有标准的方法来获得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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 获取每字节位数的标准方法是宏`CHAR_BIT`. (3认同)