Reputation: 2824
I need to work with a binary number.
I tried writing:
const char x = 00010000;
But it didn't work.
I know that I can use a hexadecimal number that has the same value as 00010000
, but I want to know if there is a type in C++ for binary numbers, and if there isn't, is there another solution for my problem?
Upvotes: 252
Views: 506574
Reputation: 31
The following preprocessor macros give you binary literals.
#define BIT(b, i) (unsigned char)!!(#b[i]-'0')
#define B(b) ( \
sizeof(#b) <= 1 \
? BIT(0,0) \
: sizeof(#b) == 2 \
? BIT(b,0) \
: sizeof(#b) == 3 \
? BIT(b,0)<<1|BIT(b,1) \
: sizeof(#b) == 4 \
? BIT(b,0)<<2|BIT(b,1)<<1|BIT(b,2) \
: sizeof(#b) == 5 \
? BIT(b,0)<<3|BIT(b,1)<<2|BIT(b,2)<<1|BIT(b,3) \
: sizeof(#b) == 6 \
? BIT(b,0)<<4|BIT(b,1)<<3|BIT(b,2)<<2|BIT(b,3)<<1|BIT(b,4) \
: sizeof(#b) == 7 \
? BIT(b,0)<<5|BIT(b,1)<<4|BIT(b,2)<<3|BIT(b,3)<<2|BIT(b,4)<<1|BIT(b,5) \
: sizeof(#b) == 8 \
? BIT(b,0)<<6|BIT(b,1)<<5|BIT(b,2)<<4|BIT(b,3)<<3|BIT(b,4)<<2|BIT(b,5)<<1|BIT(b,6) \
: BIT(b,0)<<7|BIT(b,1)<<6|BIT(b,2)<<5|BIT(b,3)<<4|BIT(b,4)<<3|BIT(b,5)<<2|BIT(b,6)<<1|BIT(b,7) \
)
char const x = B(00010000);
Upvotes: 1
Reputation: 845
Binary constants are to be standardised in C23. As of writing, 6.4.4.1/4 of the latest C2x draft standard says of the proposed notation:
[...] A binary constant consists of the prefix 0b or 0B followed by a sequence of the digits 0 or 1.
Upvotes: 2
Reputation: 935
I nominate my solution:
#define B(x) \
((((x) >> 0) & 0x01) \
| (((x) >> 2) & 0x02) \
| (((x) >> 4) & 0x04) \
| (((x) >> 6) & 0x08) \
| (((x) >> 8) & 0x10) \
| (((x) >> 10) & 0x20) \
| (((x) >> 12) & 0x40) \
| (((x) >> 14) & 0x80))
const uint8 font6[] = {
B(00001110), //[00]
B(00010001),
B(00000001),
B(00000010),
B(00000100),
B(00000000),
B(00000100),
B(00000000),
I define 8-bit fonts and graphics this way, but could work with wider fonts as well. The macro B can be defined to produce the 0b format, if supported by the compiler. Operation: the binary numbers are interpreted in octal, and then the bits are masked and shifted together. The intermediate value is limited by the largest integer the compiler can work with, I guess 64 bits should be OK.
It's entirely processed by the compiler, no code needed runtime.
Upvotes: 1
Reputation: 5665
From C++14 you can use Binary Literals, now they are part of the language:
unsigned char a = 0b00110011;
Upvotes: 4
Reputation: 1
usage : BINARY(00010001);
int BINARY(int a){ int b = 0;
for (int i = 0;i < 8;i++){
b += a % 10 << i;
a = a / 10;
}
return b;
}
Upvotes: -3
Reputation: 1
Here is my function without adding Boost library :
usage : BOOST_BINARY(00010001);
int BOOST_BINARY(int a){
int b = 0;
for (int i = 0;i < 8;i++){
b += a % 10 << i;
a = a / 10;
}
return b;
}
Upvotes: 0
Reputation: 66661
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.)
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
.
#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.
Upvotes: 72
Reputation: 42109
As already answered, the C standards have no way to directly write binary numbers. There are compiler extensions, however, and apparently C++14 includes the 0b
prefix for binary. (Note that this answer was originally posted in 2010.)
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
…
This results in only 256 #define
s, and if larger than 8-bit binary constants are needed, these definitions can be combined with shifts and ORs, possibly with helper macros (e.g., BIN16(B00000001,B00001010)
). (Having individual macros for every 16-bit, let alone 32-bit, value is not plausible.)
Of course the downside is that this syntax requires writing all the leading zeroes, but this may also make it clearer for uses like setting bit flags and contents of hardware registers. For a function-like macro resulting in a syntax without this property, see bithacks.h
linked above.
Upvotes: 20
Reputation: 1
You could try using an array of bool
:
bool i[8] = {0,0,1,1,0,1,0,1}
Upvotes: -11
Reputation: 13356
C++ provides a standard template named std::bitset
. Try it if you like.
Upvotes: -2
Reputation: 2740
Just use the standard library in C++:
#include <bitset>
You need a variable of type std::bitset
:
std::bitset<8ul> x;
x = std::bitset<8>(10);
for (int i = x.size() - 1; i >= 0; i--) {
std::cout << x[i];
}
In this example, I stored the binary form of 10
in x
.
8ul
defines the size of your bits, so 7ul
means seven bits and so on.
Upvotes: 0
Reputation: 825
You can also use inline assembly like this:
int i;
__asm {
mov eax, 00000000000000000000000000000000b
mov i, eax
}
std::cout << i;
Okay, it might be somewhat overkill, but it works.
Upvotes: 6
Reputation: 6718
You can use binary literals. They are standardized in C++14. For example,
int x = 0b11000;
Support in GCC began in GCC 4.3 (see https://gcc.gnu.org/gcc-4.3/changes.html) as extensions to the C language family (see https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html#C-Extensions), but since GCC 4.9 it is now recognized as either a C++14 feature or an extension (see Difference between GCC binary literals and C++14 ones?)
Support in Visual Studio started in Visual Studio 2015 Preview (see https://www.visualstudio.com/news/vs2015-preview-vs#C++).
Upvotes: 155
Reputation: 369
A few compilers (usually the ones for microcontrollers) has a special feature implemented within recognizing literal binary numbers by prefix "0b..." preceding the number, although most compilers (C/C++ standards) don't have such feature and if it is the case, here it is my alternative solution:
#define B_0000 0
#define B_0001 1
#define B_0010 2
#define B_0011 3
#define B_0100 4
#define B_0101 5
#define B_0110 6
#define B_0111 7
#define B_1000 8
#define B_1001 9
#define B_1010 a
#define B_1011 b
#define B_1100 c
#define B_1101 d
#define B_1110 e
#define B_1111 f
#define _B2H(bits) B_##bits
#define B2H(bits) _B2H(bits)
#define _HEX(n) 0x##n
#define HEX(n) _HEX(n)
#define _CCAT(a,b) a##b
#define CCAT(a,b) _CCAT(a,b)
#define BYTE(a,b) HEX( CCAT(B2H(a),B2H(b)) )
#define WORD(a,b,c,d) HEX( CCAT(CCAT(B2H(a),B2H(b)),CCAT(B2H(c),B2H(d))) )
#define DWORD(a,b,c,d,e,f,g,h) HEX( CCAT(CCAT(CCAT(B2H(a),B2H(b)),CCAT(B2H(c),B2H(d))),CCAT(CCAT(B2H(e),B2H(f)),CCAT(B2H(g),B2H(h)))) )
// Using example
char b = BYTE(0100,0001); // Equivalent to b = 65; or b = 'A'; or b = 0x41;
unsigned int w = WORD(1101,1111,0100,0011); // Equivalent to w = 57155; or w = 0xdf43;
unsigned long int dw = DWORD(1101,1111,0100,0011,1111,1101,0010,1000); //Equivalent to dw = 3745774888; or dw = 0xdf43fd28;
Disadvantages (it's not such a big ones):
Advantages:
spending processor time
in pointless operations (like "?.. :..", "<<", "+"
) to the executable program (it may be performed hundred of times in the final application);"mainly in C"
compilers and C++ as well (template+enum solution works only in C++ compilers
);"enum solution" (usually 255 = reach enum definition limit)
, differently, "literal constant" limitations, in the compiler allows greater numbers;several header files
(in most cases not easily readable and understandable, and make the project become unnecessarily confused and extended, like that using "BOOST_BINARY()"
);Upvotes: 36
Reputation: 34958
If you are using GCC then you can use a GCC extension (which is included in the C++14 standard) for this:
int x = 0b00010000;
Upvotes: 336
Reputation: 1821
I extended the good answer given by @renato-chandelier by ensuring the support of:
_NIBBLE_(…)
– 4 bits, 1 nibble as argument_BYTE_(…)
– 8 bits, 2 nibbles as arguments_SLAB_(…)
– 12 bits, 3 nibbles as arguments_WORD_(…)
– 16 bits, 4 nibbles as arguments_QUINTIBBLE_(…)
– 20 bits, 5 nibbles as arguments_DSLAB_(…)
– 24 bits, 6 nibbles as arguments_SEPTIBBLE_(…)
– 28 bits, 7 nibbles as arguments_DWORD_(…)
– 32 bits, 8 nibbles as argumentsI am actually not so sure about the terms “quintibble” and “septibble”. If anyone knows any alternative please let me know.
Here is the macro rewritten:
#define __CAT__(A, B) A##B
#define _CAT_(A, B) __CAT__(A, B)
#define __HEX_0000 0
#define __HEX_0001 1
#define __HEX_0010 2
#define __HEX_0011 3
#define __HEX_0100 4
#define __HEX_0101 5
#define __HEX_0110 6
#define __HEX_0111 7
#define __HEX_1000 8
#define __HEX_1001 9
#define __HEX_1010 a
#define __HEX_1011 b
#define __HEX_1100 c
#define __HEX_1101 d
#define __HEX_1110 e
#define __HEX_1111 f
#define _NIBBLE_(N1) _CAT_(0x, _CAT_(__HEX_, N1))
#define _BYTE_(N1, N2) _CAT_(_NIBBLE_(N1), _CAT_(__HEX_, N2))
#define _SLAB_(N1, N2, N3) _CAT_(_BYTE_(N1, N2), _CAT_(__HEX_, N3))
#define _WORD_(N1, N2, N3, N4) _CAT_(_SLAB_(N1, N2, N3), _CAT_(__HEX_, N4))
#define _QUINTIBBLE_(N1, N2, N3, N4, N5) _CAT_(_WORD_(N1, N2, N3, N4), _CAT_(__HEX_, N5))
#define _DSLAB_(N1, N2, N3, N4, N5, N6) _CAT_(_QUINTIBBLE_(N1, N2, N3, N4, N5), _CAT_(__HEX_, N6))
#define _SEPTIBBLE_(N1, N2, N3, N4, N5, N6, N7) _CAT_(_DSLAB_(N1, N2, N3, N4, N5, N6), _CAT_(__HEX_, N7))
#define _DWORD_(N1, N2, N3, N4, N5, N6, N7, N8) _CAT_(_SEPTIBBLE_(N1, N2, N3, N4, N5, N6, N7), _CAT_(__HEX_, N8))
And here is Renato's using example:
char b = _BYTE_(0100, 0001); /* equivalent to b = 65; or b = 'A'; or b = 0x41; */
unsigned int w = _WORD_(1101, 1111, 0100, 0011); /* equivalent to w = 57155; or w = 0xdf43; */
unsigned long int dw = _DWORD_(1101, 1111, 0100, 0011, 1111, 1101, 0010, 1000); /* Equivalent to dw = 3745774888; or dw = 0xdf43fd28; */
Upvotes: 2
Reputation: 14632
You can use a bitset
bitset<8> b(string("00010000"));
int i = (int)(bs.to_ulong());
cout<<i;
Upvotes: 2
Reputation: 207
The C++ over-engineering mindset is already well accounted for in the other answers here. Here's my attempt at doing it with a C, keep-it-simple-ffs mindset:
unsigned char x = 0xF; // binary: 00001111
Upvotes: 19
Reputation: 1
Based on some other answers, but this one will reject programs with illegal binary literals. Leading zeroes are optional.
template<bool> struct BinaryLiteralDigit;
template<> struct BinaryLiteralDigit<true> {
static bool const value = true;
};
template<unsigned long long int OCT, unsigned long long int HEX>
struct BinaryLiteral {
enum {
value = (BinaryLiteralDigit<(OCT%8 < 2)>::value && BinaryLiteralDigit<(HEX >= 0)>::value
? (OCT%8) + (BinaryLiteral<OCT/8, 0>::value << 1)
: -1)
};
};
template<>
struct BinaryLiteral<0, 0> {
enum {
value = 0
};
};
#define BINARY_LITERAL(n) BinaryLiteral<0##n##LU, 0x##n##LU>::value
Example:
#define B BINARY_LITERAL
#define COMPILE_ERRORS 0
int main (int argc, char ** argv) {
int _0s[] = { 0, B(0), B(00), B(000) };
int _1s[] = { 1, B(1), B(01), B(001) };
int _2s[] = { 2, B(10), B(010), B(0010) };
int _3s[] = { 3, B(11), B(011), B(0011) };
int _4s[] = { 4, B(100), B(0100), B(00100) };
int neg8s[] = { -8, -B(1000) };
#if COMPILE_ERRORS
int errors[] = { B(-1), B(2), B(9), B(1234567) };
#endif
return 0;
}
Upvotes: 5
Reputation: 308111
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
.
Upvotes: 11
Reputation: 84151
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
).
Upvotes: 13
Reputation: 58667
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.
Upvotes: 76
Reputation: 47075
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.)
Upvotes: 22
Reputation: 49156
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].
Upvotes: 3
Reputation: 347206
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.
Upvotes: 7