Skip to content

Binary representation

与binary representation密切相关的一个概念是:Endianness,在工程Hardware的CPU\Endianess对它进行了描述。

本文描述的binary representation其实就是在cppreference Object#Object representation and value representation章节中描述的object representation。

Print a number in binary form

下面程序都是在如下CPU中测试的:

Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian

stackoverflow How to print (using cout) a number in binary form?

A: use std::bitset

The easiest way is probably to create an std::bitset representing the value, then stream that to cout.

#include <bitset>
#include <iostream>
int main()
{
    char a = 1;
    std::bitset<8> x(a);
    std::cout << x << '\n';

    short c = 1;
    std::bitset<16> y(c);
    std::cout << y << '\n';
}
// g++ test.cpp

NOTE: 上述程序的输出:

00000001
0000000000000001

通过上面的输出可以看出,通过std::bitset并不能够真实地或者CPU是big endian还是little endian,因为它已经将结果自动转换为big endian了。

A: use reinterpret_cast andstd::bitset

If you want to display the bit representation of any object, not just an integer, remember to reinterpret as a char array first, then you can print the contents of that array, as hex, or even as binary (via 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()
{
    int a, b;
    short c;
    a = 1;
    c = 2;
    b = a << 3;
    show_binrep(a);
    show_binrep(b);
    show_binrep(c);
    float f = 1;
    show_binrep(f);
}
// g++ test.cpp

NOTE:

上述程序能够真实地反映CPU的Endianness。

上运行上述程序的输出如下:

00000001 00000000 00000000 00000000 00001000 00000000 00000000 00000000 00000010 00000000 00000000 00000000 10000000 00111111

Note that most common systems are little-endian, so the output of show_binrep(c) is not the 1111111 011000101 you expect, because that's not how it's stored in memory. If you're looking for value representation in binary, then a simple cout << bitset<16>(c) works.

A: C-style aliasing

#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);
    }
}
// g++ test.cpp

A: std::bitset

#include<iostream>
#include<sstream>
#include <bitset>
#include <stdint.h>

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);
}
// g++ test.cpp

A: std::bitset

#include <iostream>
#include <bitset>
#include <climits>
#include <stdint.h>
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;
}
int main()
{

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