305

I'm following a college course about operating systems and we're learning how to convert from binary to hexadecimal, decimal to hexadecimal, etc. and today we just learned how signed/unsigned numbers are stored in memory using the two's complement (~number + 1).

We have a couple of exercises to do on paper and I would like to be able to verify my answers before submitting my work to the teacher. I wrote a C++ program for the first few exercises but now I'm stuck as to how I could verify my answer with the following problem:

char a, b;

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

b = a >> 3;

and we need to show the binary representation in memory of a, b and c.

I've done it on paper and it gives me the following results (all the binary representations in memory of the numbers after the two's complement):

a = 00111010 (it's a char, so 1 byte)

b = 00001000 (it's a char, so 1 byte)

c = 11111110 11000101 (it's a short, so 2 bytes)

Is there a way to verify my answer? Is there a standard way in C++ to show the binary representation in memory of a number, or do I have to code each step myself (calculate the two's complement and then convert to binary)? I know the latter wouldn't take so long but I'm curious as to if there is a standard way to do so.

Community
  • 1
  • 1
Jesse Emond
  • 7,180
  • 7
  • 32
  • 37
  • 3
    do you understand hexadecimal representation? if you do, you can print the hex representation (using the `std::hex`) manipulator - I'll leave it as an exercise for you to work out the rest... – Nim Sep 08 '11 at 14:34
  • 4
    You emphasize "in memory" a lot, but I hope they're not making you deal with endian issues. – Mark Ransom Sep 08 '11 at 14:34
  • 1
    Do you know have any idea about what endianness is? If you do, do you care about it for this exercise? The answer to these questions may influence the answer to your question. – R. Martinho Fernandes Sep 08 '11 at 14:35
  • Depending on your IDE, if you are just looking to verify correctness of your hand-written solution and not actually writing a program to display something useful, you could use something like Visual Studio's memory viewer to view the exact contents of memory. – Kiley Naro Sep 08 '11 at 14:36
  • The Windows calculator does that for you. If you're not on Windows, I'm sure other operating systems come with such a thing, too. – sbi Sep 08 '11 at 14:39
  • 3
    Even Google does this, for instance [“-58 in binary”](http://www.google.com/search?q=-58%20in%20binary) – but +1 for wanting to find out how to do it yourself in code. – Konrad Rudolph Sep 08 '11 at 15:05
  • Even at a glance, all those numbers look wrong. `-58` is negative, so I immediately know the first bit should be a `1`, but your answer has the first bit `0`. And `00111010` right shifted 3 bits is `000 00111`, no math involved, so that answer is wrong too. – Mooing Duck Nov 07 '22 at 18:02

13 Answers13

566

The easiest way is probably to create an std::bitset representing the value, then stream that to 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';
Morgoth
  • 4,935
  • 8
  • 40
  • 66
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • 2
    Excuse my ignorance, but will this only show the binary representation of a number (e.g. 8 would be 00001000) or its memory representation (e.g. how -8 would be stored by taking care of the sign bit and using the "two's complement")? – Jesse Emond Sep 08 '11 at 14:41
  • 12
    @Jesse: `bitset`'s constructor argument is interpreted as an unsigned value, which works out the same as two's complement. Strictly speaking, C++ does not guarantee two's complement arithmetic, and also the `-58 >> 3` operation in your example is undefined. – Potatoswatter Sep 08 '11 at 14:46
  • Can I typecast the bitset value (i.e, x or y in this example) to a char*? – nirvanaswap Mar 16 '16 at 05:04
  • 1
    @nirvanaswap: I suppose you can cast it, but the result is unlikely to be useful. If you need the result as a string, use `bitset`'s `to_string` member. – Jerry Coffin Mar 16 '16 at 05:28
  • 1
    Thanks Jerry, I discovered to_string minutes later. FYI, casting doesn't work, the bitset variable is an object of some really arcane-looking bitset3ul (?!) class. Best to let the abstractions do the work! – nirvanaswap Mar 16 '16 at 05:39
  • how to do it in C? Also i want to ask when does 2's complment perform , for exmaple if i write unsigned int a = 2 and when signed int a = 2 , do the signed one store 2 as 2's complement `11111111 11111111 11111111 11111101` or does it gets stored in usual way `00000000 00000000 00000000 00000010` . what is the deciding factor of whether to perform 2's complement or not? This question is bugging me for a while. – Suraj Jain Dec 29 '16 at 13:19
  • How to separate bytes when printing the bits? – Beyondo Aug 18 '19 at 12:46
  • Okay nevermind; I've tried getting the bit-string through `bitset::to_string()` then used [this helpful answer](https://stackoverflow.com/a/36458653/8524922) to separate by a space every 8 bits: **`separate<8, ' '>(s);`** – Beyondo Aug 18 '19 at 12:53
  • `std::cout << std::bitset<8>(a); << std::endl` is a nice one liner – rrswa Apr 21 '20 at 10:33
156

Use on-the-fly conversion to std::bitset. No temporary variables, no loops, no functions, no macros.

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

Prints:

a = 11000110
b = 11111000
c = 1111111011000101
rocambille
  • 15,398
  • 12
  • 50
  • 68
r233967
  • 1,569
  • 1
  • 9
  • 2
63

In C++20 you can use std::format to do this:

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

Output:

11000110

On older systems you can use the {fmt} library, std::format is based on. {fmt} also provides the print function that makes this even easier and more efficient (godbolt):

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

Disclaimer: I'm the author of {fmt} and C++20 std::format.

vitaut
  • 49,672
  • 25
  • 199
  • 336
29

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

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.

Cubbi
  • 46,567
  • 13
  • 103
  • 169
13

Is there a standard way in C++ to show the binary representation in memory of a number [...]?

No. There's no std::bin, like std::hex or std::dec, but it's not hard to output a number binary yourself:

You output the left-most bit by masking all the others, left-shift, and repeat that for all the bits you have.

(The number of bits in a type is sizeof(T) * CHAR_BIT.)

sbi
  • 219,715
  • 46
  • 258
  • 445
5

Similar to what is already posted, just using bit-shift and mask to get the bit; usable for any type, being a template (only not sure if there is a standard way to get number of bits in 1 byte, I used 8 here).

#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);
    }
}
gsamaras
  • 71,951
  • 46
  • 188
  • 305
eudoxos
  • 18,545
  • 10
  • 61
  • 110
4

Reusable function:

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

Usage:

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

This works with all kind of integers.

Shital Shah
  • 63,284
  • 17
  • 238
  • 185
2

Using the std::bitset answers and convenience templates:

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

Using it like this:

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;

Generates output:

c: A binary: 01000001
x: 1234 binary: 00000000000000000000010011010010
z: -1024 binary: 1111111111111111111111111111111111111111111111111111110000000000
0
#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
}
0

Using old C++ version, you can use this snippet :

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
Ratah
  • 299
  • 3
  • 11
0

I have had this problem when playing competitive coding games online. Here is a solution that is quick to implement and is fairly intuitive. It also avoids outputting leading zeros or relying on <bitset>

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

std::cout << s;

You should note however that this solution will increase your runtime, so if you are competing for optimization or not competing at all you should use one of the other solutions on this page.

Richy
  • 1
-5

Here is the true way to get binary representation of a number:

unsigned int i = *(unsigned int*) &x;
-13

Is this what you're looking for?

std::cout << std::hex << val << std::endl;
Kevin
  • 24,871
  • 19
  • 102
  • 158
  • 35
    **Moderator Note** I _tried_ to purge antagonistic or otherwise non constructive comments under this answer selectively, and I ended up with a very broken conversation. All comments were purged. Please keep comments professional, constructive and most of all on topic. If the OP wanted to remove this, the OP would have removed it by now. If you disagree with this answer, then vote. If you can improve this answer, edit. ``. Really, we're adults, yes? I almost checked the ages on all that commented here to make sure everyone was over 13. – Tim Post Sep 08 '11 at 15:26