tags:

views:

866

answers:

10

I need to work with a binary number.

I tried writing:

const x = 00010000 ;

But it didn't work.

I know that I can use an hexadecimal number that has the same value as 00010000 but I want to know if there is a type in C++ for binary numbers & if there isn't, is there another solution for my problem?

+6  A: 

The smallest unit you can work with is a byte (which is of char type). You can work with bits though by using bitwise operators.

As for integer literals, you can only work with decimal (base 10), octal (base 8) or hexadecimal (base 16) numbers. There are no binary (base 2) literals in C nor C++.

Octal numbers are prefixed with 0 and hexadecimal numbers are prefixed with 0x. Decimal numbers have no prefix.

In C++0x you'll be able to do what you want by the way via user defined literals.

Brian R. Bondy
can i at least show the Binary value of an hexadecimal in a print or a cout function ?
hamza
Yes you can `<shameless_plug>` http://stackoverflow.com/questions/2611764#2611883 `</shameless_plug>`
vladr
Some C compilers support 0b100101 for binary literals, but it is a nonstandard extension, unfortunately.
Joey Adams
Note that, while it's not defined in the standard, some compilers (notably ones for microcontrollers and embedded systems) add the syntax for binary in the form `0b00101010` as a convenience. SDCC is one, and I'm sure there are others that do, too. (Edit: Hah, beat me to it, @Joey!)
Matt B.
And GCC, too, since 4.3: http://gcc.gnu.org/gcc-4.3/changes.html
Matt B.
+5  A: 

This thread may help.

/* Helper macros */
#define HEX__(n) 0x##n##LU
#define B8__(x) ((x&0x0000000FLU)?1:0) \
+((x&0x000000F0LU)?2:0) \
+((x&0x00000F00LU)?4:0) \
+((x&0x0000F000LU)?8:0) \
+((x&0x000F0000LU)?16:0) \
+((x&0x00F00000LU)?32:0) \
+((x&0x0F000000LU)?64:0) \
+((x&0xF0000000LU)?128:0)

/* User macros */
#define B8(d) ((unsigned char)B8__(HEX__(d)))
#define B16(dmsb,dlsb) (((unsigned short)B8(dmsb)<<8) \
+ B8(dlsb))
#define B32(dmsb,db2,db3,dlsb) (((unsigned long)B8(dmsb)<<24) \
+ ((unsigned long)B8(db2)<<16) \
+ ((unsigned long)B8(db3)<<8) \
+ B8(dlsb))


#include <stdio.h>

int main(void)
{
    // 261, evaluated at compile-time
    unsigned const number = B16(00000001,00000101);

    printf("%d \n", number);
    return 0;
}

It works! (All the credits go to Tom Torfs.)

Federico Ramponi
hamza
The B8 macro works by converting the "binary" literal to a hex literal and extracting every 4th bit.
dan04
I wonder what 0x##n##LU means? Never encountered such syntax.
Federico Ramponi
@hamza: it is indeed rather intricate. But what you need to understand is just from #include<stdio> onwards.
Federico Ramponi
@Federico: The `##` preprocessor operator pastes tokens together. So, in this case, if you call `HEX__(10)`, it expands to `0x10LU`.
James McNellis
+1 for nifty macros
Till
Very clever. You don't even need to worry about the literal being interpreted as octal since it simply gets concatenated directly to the `0x`. Leading zeros are completely optional.
Matt B.
+1  A: 

C does not have native notation for pure binary numbers. Your best bet here would be either octal (e.g. 07777) of hexadecimal (e.g. 0xfff).

Nikolai N Fetissov
+1  A: 

The "type" of a binary number is the same as any decimal, hex or octal number: int (or even char, short, long long).

When you assign a constant, you can't assign it with 11011011 (curiously and unfortunately), but you can use hex. Hex is a little easier to mentally translate. Chunk in nibbles (4 bits) and translate to a character in [0-9a-f].

Stephen
+1  A: 

As already answered, there is no way to directly write binary numbers. However, one popular workaround is to include a header file with helper macros. One easy option is also to generate a file that includes macro definitions for all 8-bit patterns, e.g.:

#define B00000000 0
#define B00000001 1
#define B00000010 2
…

These macros can easily be combined into larger quantities with shift operations (and you can make a macro for that, too, if you find yourself doing that often).

Arkku
So, how large a file would the CPP need to read if you had all the macros for a `long long int`?
wilhelmtell
@wilhelmtell: And what is the relevance of that when I specified “all *8-bit* patterns” (= 256 lines), and suggested combining larger quantities from those? Even the BOOST_BINARY of the accepted answer defines all 8-bit patterns in the header…
Arkku
+13  A: 
template<unsigned long N>
struct bin {
    enum { value = (N%10)+2*bin<N/10>::value };
} ;

template<>
struct bin<0> {
    enum { value = 0 };
} ;

// ...
    std::cout << bin<1000>::value << '\n';

The leftmost digit of the literal still has to be 1, but nonetheless.

wilhelmtell
+1, bravo. I don't think you quite answered the question, but bravo.
Stephen
</3 ::::::::::::
wilhelmtell
+1 for nifty template
Till
Better version: http://bitbucket.org/kniht/scraps/src/tip/cpp/binary.hpp (`binary<10>::value == binary<010>::value` and some error checking)
Roger Pate
Somehow missed this one before I posted my own nearly identical answer. But in mine the leading digit has to be 0, not 1.
Mark Ransom
+1. Boost Binary is the Crisco of base conversion. This is good AND healthy.
Potatoswatter
+10  A: 

You can use BOOST_BINARY while waiting for C++0x. :) BOOST_BINARY arguably has an advantage over template implementation insofar as it can be used in C programs as well (it is 100% preprocessor-driven.)

UPDATE

To do the converse (i.e. print out a number in binary form), you can use the non-portable itoa function, or implement your own.

Unfortunately you cannot do base 2 formatting with STL streams (since setbase will only honour bases 8, 10 and 16), but you can use either a std::string version of itoa, or (the more concise, yet marginally less efficient) std::bitset.

(Thank you Roger for the bitset tip!)

#include <boost/utility/binary.hpp>
#include <stdio.h>
#include <stdlib.h>
#include <bitset>
#include <iostream>
#include <iomanip>

using namespace std;

int main() {
  unsigned short b = BOOST_BINARY( 10010 );
  char buf[sizeof(b)*8+1];
  printf("hex: %04x, dec: %u, oct: %06o, bin: %16s\n", b, b, b, itoa(b, buf, 2));
  cout << setfill('0') <<
    "hex: " << hex << setw(4) << b << ", " <<
    "dec: " << dec << b << ", " <<
    "oct: " << oct << setw(6) << b << ", " <<
    "bin: " << bitset< 16 >(b) << endl;
  return 0;
}

produces:

hex: 0012, dec: 18, oct: 000022, bin:            10010
hex: 0012, dec: 18, oct: 000022, bin: 0000000000010010

Also read Herb Sutter's The String Formatters of Manor Farm for an interesting discussion.

Cheers, V.

vladr
I think this is the best answer
Ray Hidayat
As the very page to which you link says, you may only use 8, 10, or 16 with setbase. However: `int main() { cout << bitset<8>(42); }`
Roger Pate
@Roger thanks for the `bitset` tip, I already corrected the bit about `setbase` before I saw your comment though.
vladr
setw only affects the next value to be printed (no need to reset).
UncleBens
@UncleBens quite true. Updated accordingly, thanks!
vladr
+1  A: 

C++ provide a standard template named bitset. Try it if you like.

Summer_More_More_Tea
+1  A: 

You can use the function found in this question to get up to 22 bits in C++. Here's the code from the link, suitably edited:

template< unsigned long long N >
struct binary
{
  enum { value = (N % 8) + 2 * binary< N / 8 > :: value } ;
};

template<>
struct binary< 0 >
{
  enum { value = 0 } ;
};

So you can do something like binary<0101011011>::value.

Mark Ransom
+3  A: 

If you are using GCC then you can use GCC extension for this:

int x = 0b00010000;
qrdl
`0b`, not `ob`.
KennyTM
@KennyTM Fixed. Thank you.
qrdl
Several other compilers have this or other similar ways of expressing numbers in base 2.
nategoose