272

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

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

char a, b;

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

b = a >> 3;

我们需要在内存中显示ab的二进制表示c

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

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

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

c = 11111110 11000101(很短,所以2个字节)

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

4

12 回答 12

517

最简单的方法可能是创建一个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';
于 2011-09-08T14:35:55.750 回答
134

使用即时转换为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;
}

印刷:

a = 11000110
b = 11111000
c = 1111111011000101
于 2013-03-17T07:39:35.657 回答
37

在 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

于 2020-12-16T20:50:41.603 回答
27

如果您想显示任何对象的位表示,而不仅仅是整数,请记住首先重新解释为 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);
}

请注意,最常见的系统是小端的,因此输出show_binrep(c)不是您期望的 1111111 011000101,因为这不是它在内存中的存储方式如果您正在寻找二进制的表示,那么一个简单的cout << bitset<16>(c)工作。

于 2011-09-08T14:40:53.620 回答
13

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

不,没有std::bin, like std::hexor std::dec,但是自己输出一个二进制数并不难:

您通过屏蔽所有其他位、左移来输出最左边的位,然后对您拥有的所有位重复此操作。

(一个类型的位数是sizeof(T) * CHAR_BIT。)

于 2011-09-08T14:35:35.953 回答
6

与已经发布的类似,只是使用位移位和掩码来获取位;可用于任何类型,作为模板(只是不确定是否有标准方法来获取 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);
    }
}
于 2011-09-08T14:45:41.923 回答
4

可重复使用的功能:

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);
}

这适用于所有类型的整数。

于 2018-06-04T05:47:49.987 回答
1
#include <iostream> 
#include <cmath>       // in order to use pow() function
using namespace std; 

string show_binary(unsigned int u, int num_of_bits);

int main() 
{ 

  cout << show_binary(128, 8) << endl;   // should print 10000000
  cout << show_binary(128, 5) << endl;   // should print 00000
  cout << show_binary(128, 10) << endl;  // should print 0010000000

  return 0; 
}

string show_binary(unsigned int u, int num_of_bits) 
{ 
  string a = "";

  int t = pow(2, num_of_bits);   // t is the max number that can be represented

  for(t; t>0; t = t/2)           // t iterates through powers of 2
      if(u >= t){                // check if u can be represented by current value of t
          u -= t;
          a += "1";               // if so, add a 1
      }
      else {
          a += "0";               // if not, add a 0
      }

  return a ;                     // returns string
}
于 2015-11-04T20:40:47.987 回答
0

使用 std::bitset 答案和便利模板:

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

template<typename T>
struct BinaryForm {
    BinaryForm(const T& v) : _bs(v) {}
    const std::bitset<sizeof(T)*CHAR_BIT> _bs;
};

template<typename T>
inline std::ostream& operator<<(std::ostream& os, const BinaryForm<T>& bf) {
    return os << bf._bs;
}

像这样使用它:

auto c = 'A';
std::cout << "c: " << c << " binary: " << BinaryForm{c} << std::endl;
unsigned x = 1234;
std::cout << "x: " << x << " binary: " << BinaryForm{x} << std::endl;
int64_t z { -1024 };
std::cout << "z: " << z << " binary: " << BinaryForm{z} << std::endl;

生成输出:

c: A binary: 01000001
x: 1234 binary: 00000000000000000000010011010010
z: -1024 binary: 1111111111111111111111111111111111111111111111111111110000000000
于 2020-05-02T00:34:40.587 回答
0

使用旧的 C++ 版本,您可以使用此代码段:

template<typename T>
string toBinary(const T& t)
{
  string s = "";
  int n = sizeof(T)*8;
  for(int i=n-1; i>=0; i--)
  {
    s += (t & (1 << i))?"1":"0";
  }
  return s;
}

int main()
{
  char a, b;

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

  b = a >> 3;

  cout << "a = " << a << " => " << toBinary(a) << endl;
  cout << "b = " << b << " => " << toBinary(b) << endl;
  cout << "c = " << c << " => " << toBinary(c) << endl;
}

a = => 11000110
b = => 11111000
c = -315 => 1111111011000101
于 2019-04-14T23:29:31.073 回答
-5

这是获得数字二进制表示的真正方法:

unsigned int i = *(unsigned int*) &x;
于 2015-10-19T15:33:49.087 回答
-11

这是你要找的吗?

std::cout << std::hex << val << std::endl;
于 2011-09-08T14:33:50.787 回答