Могу ли я использовать двоичный литерал в C или c++?
мне нужно работать с двоичным числом.
Я пыталась написать:
const x = 00010000;
но это не сработало.
Я знаю, что могу использовать шестнадцатеричное число, которое имеет то же значение, что и 00010000, но я хочу знать, есть ли тип в C++ для двоичных чисел, а если нет, есть ли другое решение для моей проблемы?
19 ответов:
вы можете использовать
BOOST_BINARYв ожидании C++0x.:)BOOST_BINARYвозможно, имеет преимущество перед реализацией шаблона, поскольку это может быть использован в программах C, а также (он управляется препроцессором 100%.)обновление
чтобы сделать обратное (т. е. распечатать число в двоичной форме), вы можете использовать непортативный
itoaфункции или реализовать собственный.к сожалению, вы не можете сделать базовое форматирование 2 с потоками STL (так как
setbaseбудут чтить только базы 8, 10 и 16), но вы можете использоватьstd::stringверсияitoa, или (более кратким, но незначительно менее эффективным)std::bitset.(спасибо Роджер на
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; }выдает:
hex: 0012, dec: 18, oct: 000022, bin: 10010 hex: 0012, dec: 18, oct: 000022, bin: 0000000000010010также читайте Херба Саттера строка форматирования из фермерской усадьбы для интересного обсуждения.
Если вы используете GCC, то вы можете использовать расширение GCC (входит в стандарт C++14) для этого:
int x = 0b00010000;
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';самая левая цифра литерала по-прежнему должна быть 1, но тем не менее.
вы можете использовать двоичные литералы. Они стандартизированы в C++14. Например,
int x = 0b11000;поддержка в GCC
поддержка в GCC началась в GCC 4.3 (см. https://gcc.gnu.org/gcc-4.3/changes.html) Как расширения семейства языков C (см. https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html#C-Extensions), но так как GCC 4.9 теперь распознается либо как функция C++14, либо как расширение (см. разница между двоичным GCC литералы и C++14 из них?)
поддержка в Visual Studio
поддержка в Visual Studio начала в Visual Studio 2015 для предварительного просмотра (см. раздел https://www.visualstudio.com/news/vs2015-preview-vs#C++).
несколько компиляторов (обычно те, для микроконтроллеры) имеет специальную функцию, реализованную в распознавании буквенных двоичных чисел с помощью префикс " 0b..." предшествующий номер, хотя большинство компиляторов (стандарты C / C++) не имеют такой функции, и если это так, вот мое альтернативное решение:
#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;недостатки (это не такие большие):
- двоичные числа должны быть сгруппированы 4 на 4.
- двоичные литералы должны быть только беззнаковыми целыми числами;
преимущества:
- всего препроцессор управляется, а не
spending processor timeв бессмысленные операции (like "?.. :..", "<<", "+") к исполняемой программе (она может быть выполнена сто раз в конечном приложении);- он работает
"mainly in C"компиляторы и C++, а также (template+enum solution works only in C++ compilers);- оно имеет только ограничение "длинности" для выражать значения "литеральной константы". Было бы раннее ограничение длины (обычно 8 бит: 0-255) , если бы кто-то выражал постоянные значения путем разбора разрешения
"enum solution" (usually 255 = reach enum definition limit), иначе говоря, ограничения" литеральной константы", в компиляторе допускают большие числа;- некоторые другие решения требуют преувеличенного количества постоянных определений (слишком много определений, на мой взгляд), включая long или
several header files(в большинстве случаев не легко читаемый и понятный, и сделать проект стать излишне запутанный и расширенный, как это с помощью"BOOST_BINARY()");- простота решения: легко читаемый, понятный и регулируемый для других случаев (может быть расширен для группировки 8 на 8 тоже);
этой теме может помочь.
/* 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; }это работает! (Все кредиты идут тому торфу.)
как уже было сказано, стандарты C не имеют возможности напрямую записывать двоичные числа. Однако существуют расширения компилятора, и, по-видимому, C++14 включает в себя
0bпрефикс для бинарных. (Обратите внимание, что этот ответ был первоначально опубликован в 2010 году.)один популярный обходной путь должен включать файл заголовка с вспомогательными макросами. Одним из простых вариантов также является создание файла, который включает определения макросов для всех 8-битных шаблонов, например:
#define B00000000 0 #define B00000001 1 #define B00000010 2 …это приводит в только 256
#defines, и если требуется больше 8-битных двоичных констант, эти определения могут быть объединены со сдвигами и ORs, возможно, с вспомогательными макросами (например,BIN16(B00000001,B00001010)). (Наличие отдельных макросов для каждого 16-битного, не говоря уже о 32-битном, значение не является правдоподобным.)конечно, недостатком является то, что этот синтаксис требует записи всех ведущих нулей, но это также может сделать его более понятным для использования, как установка битовых флагов и содержимого аппаратных регистров. Для функционального макроса в результате синтаксис без этого свойства, см.
bithacks.hссылка на которую дана выше.
чрезмерное инженерное мышление C++ уже хорошо учтено в других ответах здесь. Вот моя попытка сделать это с помощью C, keep-it-simple-ffs mindset:
unsigned char x = 0xF; // binary: 00001111
C нет уроженца обозначения для чистых двоичных чисел. Ваш лучший выбор здесь будет либо восьмеричной (например,
07777) of шестнадцатеричное (например,0xfff).
Вы можете использовать функцию Найти в этом вопросе получить до 22 бит в C++. Вот код из ссылки, соответствующим образом отредактированный:
template< unsigned long long N > struct binary { enum { value = (N % 8) + 2 * binary< N / 8 > :: value } ; }; template<> struct binary< 0 > { enum { value = 0 } ; };Так что вы можете сделать что-то вроде
binary<0101011011>::value.
наименьшая единица, с которой вы можете работать, - это байт (который имеет
charтип). Вы можете работать с битами, хотя с помощью побитовых операторов.что касается целочисленных литералов, вы можете работать только с десятичными (основание 10), восьмеричными (основание 8) или шестнадцатеричными (основание 16) числами. Нет двоичной (основание 2) литералы в C или C++.
Восьмеричные числа начинаются с
0и шестнадцатеричные числа начинаются с0x. Десятичные числа не имеют префикса.In C++0x вы сможете делать то, что вы хотите, кстати, через пользовательские литералы.
на основе некоторых других ответов, но этот будет отклонять программы с незаконными двоичными литералами. Ведущие нули являются необязательными.
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пример:
#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; }
" тип " двоичного числа совпадает с любым десятичным, шестнадцатеричным или восьмеричным числом:
int(или даже char, короткий, длинный длинный).когда вы назначаете константу, вы не можете назначить ее с 11011011 (любопытно и к сожалению), но вы можете использовать hex. Наговор это немного легче, чтобы мысленно перевести. Кусок в грызет (4 бита) и перевести на символ в [0-9a-f].
вы также можете использовать встроенную сборку следующим образом:
int i; __asm { mov eax, 00000000000000000000000000000000b mov i, eax } std::cout << i;ладно, это может быть несколько излишне, но это работает :)
вы можете использовать bitset
bitset<8> b(string("00010000")); int i = (int)(bs.to_ulong()); cout<<i;
я расширил хороший ответ, данный @renato-chandelier, обеспечив поддержку:
_NIBBLE_(…)- 4 бита, 1 грызть в качестве аргумента_BYTE_(…)- 8 бит, 2 грызет как аргументы_SLAB_(…)- 12 бит, 3 грызет как аргументы_WORD_(…)- 16 бит, 4 грызет как аргументы_QUINTIBBLE_(…)- 20 бит, 5 грызет как аргументы_DSLAB_(…)– 24 бита, 6 грызет как аргументы_SEPTIBBLE_(…)- 28 бит, 7 грызет как аргументы_DWORD_(…)- 32 бита, 8 грызет как аргументыя на самом деле не так уверен в терминах "quintibble" и "septibble". Если кто-нибудь знает альтернативу, пожалуйста, дайте мне знать.
вот макрос переписан:
#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))а вот пример использования Ренато:
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; */
просто используйте стандартную библиотеку в C++:
#include <bitset>вам нужна переменная типа
std::bitset:std::bitset<8ul> x; x = std::bitset<8>(10); for (int i = x.size() - 1; i >= 0; i--) { std::cout << x[i]; }в этом примере я сохранил двоичный код 10 в x.
8ulопределяет размер ваших битов, так7ulозначает семь бит и так далее.
Comments