Can I use a binary literal in C or C++?
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.
Binary literals?
I'd use a bit shift operator:
const int has_nukes = 1<<0;
const int has_bio_weapons = 1<<1;
const int has_chem_weapons = 1<<2;
// ...
int dangerous_mask = has_nukes | has_bio_weapons | has_chem_weapons;
bool is_dangerous = (country->flags & dangerous_mask) == dangerous_mask;
It is even better than flood of 0's.
Writing binary number system in C code
Standard C doesn't define binary constants. There's a GNU C extension though (among popular compilers, clang adapts it as well): the 0b
or 0B
prefixes:
int foo = 0b1010;
If you want to stick with standard C, then there's an option: you can combine a macro and a function to create an almost readable "binary constant" feature:
#define B(x) S_to_binary_(#x)
static inline unsigned long long S_to_binary_(const char *s)
{
unsigned long long i = 0;
while (*s) {
i <<= 1;
i += *s++ - '0';
}
return i;
}
And then you can use it like this:
int foo = B(1010);
If you turn on heavy compiler optimizations, the compiler will most likely eliminate the function call completely (constant folding) or will at least inline it, so this won't even be a performance issue.
Proof:
The following code:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#define B(x) S_to_binary_(#x)
static inline unsigned long long S_to_binary_(const char *s)
{
unsigned long long i = 0;
while (*s) {
i <<= 1;
i += *s++ - '0';
}
return i;
}
int main()
{
int foo = B(001100101);
printf("%d\n", foo);
return 0;
}
has been compiled using clang -o baz.S baz.c -Wall -O3 -S
, and it produced the following assembly:
.section __TEXT,__text,regular,pure_instructions
.globl _main
.align 4, 0x90
_main: ## @main
.cfi_startproc
## BB#0:
pushq %rbp
Ltmp2:
.cfi_def_cfa_offset 16
Ltmp3:
.cfi_offset %rbp, -16
movq %rsp, %rbp
Ltmp4:
.cfi_def_cfa_register %rbp
leaq L_.str1(%rip), %rdi
movl $101, %esi ## <= This line!
xorb %al, %al
callq _printf
xorl %eax, %eax
popq %rbp
ret
.cfi_endproc
.section __TEXT,__cstring,cstring_literals
L_.str1: ## @.str1
.asciz "%d\n"
.subsections_via_symbols
So clang
completely eliminated the call to the function, and replaced its return value with 101
. Neat, huh?
C++ Binary Literal
Binary literals have been a compiler extension in GCC long before C++14 standardized them. You can compile with -pedantic
to warn on extensions and -pedantic-errors
to elevate those specific warnings to errors:
<source>:3:11: error: binary constants are a C++14 feature or GCC extension
3 | int a = 0b1010; // an error is expected
| ^~~~~~
Separator to make binary literals look cleaner
If you always have the same number of bits (32 in your example) you could #define a macro a bit like this:
#define BITS32(b1,b2,b3,b4,b5,b6,b7,b8) ( \
((b1) << 28) + \
((b2) << 24) + \
((b3) << 20) + \
((b4) << 16) + \
((b5) << 12) + \
((b6) << 8) + \
((b7) << 4) + \
(b8))
and then call it like this:
uint32_t branch_bitmask = BITS32(0b0000,0b1111,0b0000,0b0000,0b0000,0b0000,0b0000,0b0000);
or you can go further and use ##
in the macro to prepend the 0b
.
But the simple answer for me has always been to use hexadecimal, as one hex digit is 4 bits.
C represent int in base 2
The standard describes no way to create "binary literals". However, the latest versions of GCC and Clang support this feature using a syntax similar to the hex syntax, except it's b
instead of x
:
int foo = 0b00100101;
As stated, using such binary literals locks you out of Visual Studio's C and C++ compilers, so you may want to take care where and how you use them.
C++14 (I know, I know, this isn't C) standardizes support for binary literals.
What does 0b and 0x stand for when assigning binary and hex?
Any and all integer literals you can create are summarized in the C++ standard by the grammar production at [lex.icon]
integer-literal:
binary-literal integer-suffixopt
octal-literal integer-suffixopt
decimal-literal integer-suffixopt
hexadecimal-literal integer-suffixopt
binary-literal:
0b binary-digit
0B binary-digit
binary-literal 'opt binary-digit
octal-literal:
0
octal-literal 'opt octal-digit
decimal-literal:
nonzero-digit
decimal-literal 'opt digit
hexadecimal-literal:
hexadecimal-prefix hexadecimal-digit-sequence
binary-digit:
0
1
octal-digit: one of
0 1 2 3 4 5 6 7
nonzero-digit: one of
1 2 3 4 5 6 7 8 9
hexadecimal-prefix: one of
0x 0X
hexadecimal-digit-sequence:
hexadecimal-digit
hexadecimal-digit-sequence 'opt hexadecimal-digit
hexadecimal-digit: one of
0 1 2 3 4 5 6 7 8 9
a b c d e f
A B C D E F
As we can deduce from the grammar, there are four types of integer literals:
- Plain decimal, that must begin with a non-zero digit.
- Octal, any number with a leading 0 (including a plain 0).
- Binary, requiring the prefix
0b
or0B
. - Hexadecimal, requiring the prefix
0x
or0X
.
The leading 0 for octal numbers can be thought of as the "O" in "Octal". The other prefixes use a leading zero to mark the beginning of a number that should not be interpreted as decimal. "B" is intuitively for "binary", while "X" is for "hexadecimal".
Related Topics
Testing Pointers For Validity (C/C++)
Initializer Lists and Rhs of Operators
Why Does Rand() Yield the Same Sequence of Numbers on Every Run
Why Does Omission of "#Include ≪String≫" Only Sometimes Cause Compilation Failures
Strptime() Equivalent on Windows
Defining Static Members in C++
Why Copy Constructor Is Not Called in This Case
Get Human Readable Ast from C++ Code
How to Create a Generic Object Model For Use in Qml
How to Achieve the Theoretical Maximum of 4 Flops Per Cycle
When to Use Inline Function and When Not to Use It
How to Erase an Element from Std::Vector≪≫ by Index
Conveniently Declaring Compile-Time Strings in C++
How to Set a Breakpoint on 'Memory Access' in Gdb
What's the Difference Between Assignment Operator and Copy Constructor
C++ Display Stack Trace on Exception
What Is the Advantage of Using Forwarding References in Range-Based For Loops