Czy Mogę używać binarnego dosłownika w C lub c++?

Muszę pracować z liczbą binarną.

Próbowałem napisać:

const x = 00010000;
Ale nie zadziałało.

Wiem, że mogę użyć liczby szesnastkowej, która ma taką samą wartość jak 00010000, ale chcę wiedzieć, czy w C++ istnieje typ dla liczb binarnych, a jeśli nie, czy jest inne rozwiązanie mojego problemu?

 169
Author: Peter Mortensen, 2010-04-10

19 answers

Możesz użyć BOOST_BINARY W oczekiwaniu na C++0x.:) BOOST_BINARY prawdopodobnie ma przewagę nad implementacją szablonów o tyle, że może być używany również w programach C (jest w 100% preprocesorowy.)

UPDATE

Aby wykonać converse (tzn. wydrukować liczbę w postaci binarnej), możesz użyć nie-przenośnego itoa funkcja , lub zaimplementuj własne.

Niestety nie można formatować Bazy 2 ze strumieniami STL (od setbase będzie honorować tylko podstawy 8, 10 i 16), Ale ty możesz użyć albo std::string wersji itoa, albo (bardziej zwięzłej, ale nieznacznie mniej wydajnej) std::bitset.

(Dziękuję Roger za bitset wskazówka!)

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

Produkuje:

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

Przeczytaj też Herb Sutter ciągi znaków Manor Farm do ciekawej dyskusji.

 65
Author: vladr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:07

Jeśli używasz GCC, możesz użyć rozszerzenia GCC (które jest zawarte w standard C++14) do tego:

int x = 0b00010000;
 233
Author: qrdl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-29 15:52:55
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';

Ostatnia cyfra literału musi być 1, ale mimo to.

 73
Author: wilhelmtell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-10 01:10:00

Możesz używać literałów binarnych. Są one standaryzowane w C++14. Na przykład,

int x = 0b11000;

Wsparcie w GCC

Wsparcie w GCC zaczęło się w GCC 4.3 (zobacz https://gcc.gnu.org/gcc-4.3/changes.html ) jako rozszerzenia do rodziny języków C (patrz https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html#C-Extensions ), ale od GCC 4.9 jest teraz rozpoznawany jako funkcja C++14 lub rozszerzenie (Zobacz różnica między literałami binarnymi GCC A C++14?)

Wsparcie w Visual Studio

Wsparcie w Visual Studio rozpoczęło się w Visual Studio 2015 Preview (zobacz https://www.visualstudio.com/news/vs2015-preview-vs#C++).

 69
Author: Muhammad Annaqeeb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:07

Kilka kompilatorów (Zwykle tych dla mikrokontrolerów ) posiada specjalną funkcję zaimplementowaną w rozpoznawaniu literalnych liczb binarnych przez prefiks "0B..." poprzedzający numer, chociaż większość kompilatorów (standardy C/C++) nie ma takiej funkcji i jeśli tak jest, oto moje alternatywne rozwiązanie:

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

Wady (to nie Takie Duże):

  • liczby binarne muszą być zgrupowane 4 na 4;
  • the binary literały muszą być tylko niepodpisanymi liczbami całkowitymi;

Zalety :

  • Całkowity preprocesor sterowany, a nie spending processor time w bezsensownych operacjach (like "?.. :..", "<<", "+") do programu wykonywalnego (może być wykonywany setki razy w końcowej aplikacji);
  • Działa "mainly in C" kompilatory i C++, jak również (template+enum solution works only in C++ compilers);
  • mA tylko ograniczenie "długości" do wyrażania "literalnych stałych" wartości. Wcześniej byłoby ograniczenie długości (zwykle 8 bitów: W przeciwieństwie do innych systemów, w których nie jest możliwe zdefiniowanie wartości stałych (np. wartości stałych), nie jest możliwe zdefiniowanie wartości stałych (np. wartości stałych).]}
  • niektóre inne rozwiązania wymagają przesadnej liczby stałych definicji (moim zdaniem zbyt wielu definicji), w tym długich lub several header files (w większości przypadków niełatwo czytelnych i zrozumiałych, i sprawiają, że projekt staje się niepotrzebnie zdezorientowany i rozszerzony, jak to za pomocą "BOOST_BINARY()");
  • prostota rozwiązania: Łatwa do odczytania, zrozumiałe i regulowane dla innych przypadków (można też rozszerzyć o grupowanie 8 na 8);
 30
Author: Renato Chandelier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-29 16:08:34

Ten wątek może pomóc.

/* 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;
}
To działa! (Wszystkie napisy należą do Toma Torfsa.)
 19
Author: Federico A. Ramponi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-10 01:00:21

Jak już odpowiedziano, standardy C nie mają możliwości bezpośredniego zapisu liczb binarnych. Istnieją jednak rozszerzenia kompilatora i najwyraźniej C++14 zawiera prefiks 0b dla binarnych. (Zauważ, że odpowiedź ta została pierwotnie opublikowana w 2010 roku.)

Jednym z popularnych sposobów obejścia problemu jest dołączenie pliku nagłówkowego z pomocniczymi makrami. Jedną z łatwych opcji jest również wygenerowanie pliku zawierającego definicje makr dla wszystkich 8-bitowych wzorców, np.:

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

Daje to tylko 256 #defines, a jeśli potrzebne są większe niż 8-bitowe stałe binarne, definicje te mogą być łączone z przesunięciami i ORs, ewentualnie z pomocniczymi makrami (np. BIN16(B00000001,B00001010)). (Posiadanie pojedynczych makr dla każdego 16-bitowego, nie mówiąc już o 32-bitowym, wartość nie jest wiarygodna.)

Oczywiście minusem jest to, że składnia ta wymaga zapisu wszystkich zer wiodących, ale może to również uczynić ją jaśniejszą dla zastosowań takich jak ustawianie flag bitowych i zawartości rejestrów sprzętowych. Dla makra podobnego do funkcji, co daje składnię bez tego właściwość, patrz bithacks.h linked powyżej.

 15
Author: Arkku,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-27 10:59:55

Myślenie nad inżynierią C++ jest już dobrze uwzględnione w innych odpowiedziach tutaj. Oto moja próba zrobienia tego z C, keep-it-simple-ffs:

unsigned char x = 0xF; // binary: 00001111
 13
Author: Craig,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-07 17:50:39

C nie ma natywnej notacji dla czystych liczb binarnych. Najlepszym rozwiązaniem byłoby ósemkowe (np. 07777) z szesnastkowe (np. 0xfff).

 12
Author: Nikolai Fetissov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-10 01:52:29

Możesz użyć funkcji znalezionej w tym pytaniu , Aby uzyskać do 22 bitów w C++. Oto kod z linku, odpowiednio edytowany:

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

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

Więc możesz zrobić coś takiego binary<0101011011>::value.

 9
Author: Mark Ransom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:24

Najmniejszą jednostką, z którą możesz pracować, jest bajt (który jest typu char). Możesz pracować z bitami za pomocą operatorów bitowych.

Jeśli chodzi o literały całkowite, można pracować tylko z liczbami dziesiętnymi (baza 10), ósemkowymi (baza 8) lub szesnastkowymi (baza 16). W C ani c++nie ma literałów binarnych (base 2).

Liczby ósemkowe są poprzedzone 0, A liczby szesnastkowe są poprzedzone 0x. Liczby dziesiętne nie mają przedrostka.

W C++0x będziesz mógł zrobić to, co chcesz przy okazji za pomocą literały zdefiniowane przez użytkownika .

 7
Author: Brian R. Bondy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-10 00:42:55

Na podstawie innych odpowiedzi, ale ta odrzuci programy z nielegalnymi literałami binarnymi. Początkowe zera są opcjonalne.

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

Przykład:

#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;
}
 4
Author: Thomas Eding,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-20 21:05:02

" Typ " liczby binarnej jest taki sam jak każda liczba dziesiętna, szesnastkowa lub ósemkowa: int (lub nawet znak, krótki, długi długi).

Kiedy przypisujesz stałą, nie możesz jej przypisać za pomocą 11011011 (co ciekawe i niestety), ale możesz użyć hex. Hex jest trochę łatwiej przetłumaczyć mentalnie. Chunk in nibbles (4 bity) and translate to a character in [0-9a-f].

 2
Author: Stephen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-10 00:44:48

Możesz również użyć wbudowanego zestawu w następujący sposób:

int i;

__asm {
    mov eax, 00000000000000000000000000000000b
    mov i,   eax
}

std::cout << i;

Ok, może to trochę przesada, ale działa :)

 2
Author: renger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-17 22:09:45

Możesz użyć bitsetu

bitset<8> b(string("00010000"));
int i = (int)(bs.to_ulong());
cout<<i;
 2
Author: Deqing,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-14 00:52:53

Rozszerzyłem dobrą odpowiedź udzieloną przez @ renato-żyrandol, zapewniając wsparcie:

  • {–2]} - 4 bity, 1 bit jako argument
  • {–3]} - 8 bitów, 2 bitów jako argumenty
  • {–4]} - 12 bitów, 3 bitów jako argumenty
  • {–5]} - 16 bitów, 4 bitów jako argumenty
  • {–6]} - 20 bitów, 5 bitów jako argumenty
  • {–7]} - 24 bity, 6 bitów jako argumenty
  • {–8]} - 28 bitów, 7 bitów jako argumenty
  • _DWORD_(…) – 32 bity, 8 nibbles jako argument

Nie jestem tak pewien co do terminów "quintibble" i "septibble". Jeśli ktoś zna jakąś alternatywę proszę dać mi znać.

Oto makro przepisane:

#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))

A oto przykład użycia Renato:

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; */
 2
Author: madmurphy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-17 01:19:42

Wystarczy użyć biblioteki standardowej w C++:

#include <bitset>

Potrzebna jest zmienna typu std::bitset:

std::bitset<8ul> x;
x = std::bitset<8>(10);
for (int i = x.size() - 1; i >= 0; i--) {
      std::cout << x[i];
}

W tym przykładzie zapisałem binarny 10 W x.

8ul definiuje rozmiar twoich bitów, więc 7ul oznacza siedem bitów i tak dalej.

 0
Author: Hadi Rasekh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-12 17:38:31

C++ dostarcza standardowy szablon o nazwie bitset. Spróbuj, jeśli chcesz.

 0
Author: Summer_More_More_Tea,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-29 15:52:15

Możesz spróbować:

bool i[8] = {0,0,1,1,0,1,0,1}
 -8
Author: george wagenknecht,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-29 12:45:58