Czy istnieje typ danych „bajt” w C ++?

85

Jeśli istnieje, czy istnieje plik nagłówkowy do dołączenia?

Ten kod daje błąd kompilacji:

#include <iostream>

using namespace std;

int main()
{
    byte b = 2;

    cout << b << endl;

    return 0;
}
user2972135
źródło
15
To się nazywa char.
Avidan Borisov
12
@Ben char to koniecznie jeden bajt. Po prostu bajt to niekoniecznie 8 bitów.
Avidan Borisov
4
@Ben: Najwyraźniej nie znasz bardziej egzotycznych platform. Bajt z pewnością nie jest zdefiniowany jako 8 bitów, niezależnie od tego, że przeważają bajty 8-bitowe. Dlatego mamy CHAR_BIT. Pracowałem na więcej niż jednym systemie osadzonym, w którym bajty nie mają długości 8 bitów. Zdefiniowano znak, który ma rozmiar 1, więc tak, znak jest zawsze bajtem.
Ed S.
11
@Ben: Standardy C i C ++ jednoznacznie definiują „bajt” jako rozmiar a char, który ma co najmniej 8 bitów. Termin „bajt” może być zdefiniowany inaczej w innych kontekstach, ale omawiając C lub C ++ lepiej trzymać się definicji standardu.
Keith Thompson
3
OP, ponownie rozważę Twoją zaakceptowaną odpowiedź. Naprawdę. Ponadto, jeśli gwarantowany jest rozmiar 1 znaku, po co pisać using byte = unsigned chari robić z nim (jak sugeruje odpowiedź rmp)?
einpoklum

Odpowiedzi:

34

Nie, w C ++ nie ma bajtowego typu danych. Jednak zawsze możesz dołączyć nagłówek bitset z biblioteki standardowej i utworzyć typedef dla bajtu:

typedef bitset<8> BYTE;

Uwaga: Biorąc pod uwagę, że WinDef.h definiuje BYTE dla kodu Windows, możesz chcieć użyć czegoś innego niż BYTE, jeśli zamierzasz używać Windowsa.

Edycja: w odpowiedzi na sugestię, że odpowiedź jest nieprawidłowa. Odpowiedź nie jest zła. Pytanie brzmiało: „Czy istnieje typ danych„ bajt ”w C ++?”. Odpowiedź brzmiała i brzmi: „Nie, nie ma bajtowego typu danych w C ++”.

W odniesieniu do sugerowanej możliwej alternatywy, dla której zadano pytanie, dlaczego sugerowana alternatywa jest lepsza?

Według mojej kopii standardu C ++ w tamtym czasie:

„Obiekty zadeklarowane jako znaki (znaki) powinny być wystarczająco duże, aby przechowywać dowolny element z podstawowego zestawu znaków implementacji”: 3.9.1.1

Czytałem to, aby zasugerować, że jeśli implementacja kompilatora wymaga 16 bitów do przechowywania elementu podstawowego zestawu znaków, to rozmiar znaku będzie wynosił 16 bitów. To, że dzisiejsze kompilatory zwykle używają 8 bitów na znak, to jedno, ale z tego co wiem, z pewnością nie ma gwarancji, że będzie to 8 bitów.

Z drugiej strony „zestaw bitów szablonu klasy <N> opisuje obiekt, który może przechowywać sekwencję składającą się z ustalonej liczby bitów, N.” : 20.5.1. Innymi słowy, podając 8 jako parametr szablonu, otrzymuję obiekt, który może przechowywać sekwencję składającą się z 8 bitów.

To, czy alternatywa jest lepsza, czy nie, w kontekście pisanego programu, zależy więc, o ile rozumiem, chociaż mogę się mylić, od twojego kompilatora i twoich wymagań w tym czasie. W związku z tym do osoby piszącej kod, jeśli o mnie chodzi, należało określenie, czy sugerowana alternatywa była odpowiednia dla ich wymagań / pragnień / potrzeb.

Darren Gansberg
źródło
59
Jak jest bitset<8>lepszy niż unsigned char?
Keith Thompson
12
To nie jest. użyj znaku bez znaku
YasserAsmi
2
Odpowiedź jest błędna, a wszystkie inne są błędne, z wyjątkiem jwodder, który jest jedyną poprawną odpowiedzią. bajt to BIT_CHAR bitów, a nie 8 bitów.
Mark Galeck
14
Możesz zaktualizować tę odpowiedź, ponieważ jest terazstd::byte
NathanOliver
1
@Persixty oops, dlaczego powiedziałem BIT_CHAR. To tajemnica. Tajemnica wszechświata ..
Mark Galeck
87

Nie, bytew C ++ nie ma typu „ ”. Zamiast tego chcesz unsigned char(lub, jeśli potrzebujesz dokładnie 8 bitów, uint8_tod <cstdint>, od C ++ 11 ). Zauważ, że charniekoniecznie jest to dokładna alternatywa, ponieważ oznacza to signed charna niektórych kompilatorach i unsigned charna innych.

jwodder
źródło
8
Nie do końca. char, signed chari unsigned charsą trzema różnymi typami. charma taką samą reprezentację jak jeden z dwóch pozostałych.
Keith Thompson
2
Jeśli unsigned charjest większy niż 8 bitów, uint8_tnie zostanie zdefiniowany.
Keith Thompson
1
jeśli jesteś w celu-c, może być konieczne uwzględnienie <stdint.h>zamiast <cstdint>.
orion elenzil
2
@orionelenzil Pytanie dotyczyło C ++, a nie obiektywnego C.
Pharap
2
@pharap - osoba pisząca C lub C ++ w kontekście Objective-C może uznać mój komentarz za przydatny.
orion elenzil
42

Tak, jest std::byte(zdefiniowane w <cstddef>).

C ++ 17 wprowadził to.

maxschlepzig
źródło
2
std::bytenie może wykonać na nim arytmetyki, co może spowodować przerwanie transakcji.
Pharap
3
@Pharap, to zależy - niemożność przypadkowego wykonania arytmetyki może być postrzegana jako zaleta w niektórych przypadkach użycia. Ponieważ std::bytejest to tylko dodatek można wybrać odpowiednie narzędzia do pracy (czyli albo std::byte, char, unsigned charlub uint_8).
maxschlepzig
27

jeśli używasz systemu Windows, w WinDef.h masz:

typedef unsigned char BYTE;
rmp
źródło
22

Użycie C++11tam jest ładną wersją dla ręcznie zdefiniowanego typu bajtu:

enum class byte : std::uint8_t {};

Tak przynajmniej robi GSL .

Począwszy od C++17(prawie) ta właśnie wersja jest zdefiniowana w standardzie jako std::byte(dzięki Neil Macintosh za obie).

m8mble
źródło
4
Dlaczego Twoim zdaniem to wyliczenie jest lepsze niż typedef unsigned char byte;lub typedef std::uint8_t byte;?
einpoklum
2
@einpoklum, zwiększa bezpieczeństwo typów. Na przykład, otrzymasz błąd kompilacji, gdy przypadkowo pomnożesz taką wartość bajtu. Chociaż nie pomaga to w aliasingu . Jeśli chcesz poprawnie aliasować niektóre potrzebne bajty char*, unsigned char*lub std::byte*.
maxschlepzig
1
Z wyjątkiem std::bytetego, że nie można wykonać na nim arytmetyki, co może być przełomem.
Pharap
4

Nie, ale od C ++ 11 istnieje [u] int8_t .

Siergiej
źródło
1

Jest też byte_lite , kompatybilny z C ++ 98, C ++ 11 i nowszymi.

ruipacheco
źródło
1
namespace std
{
  // define std::byte
  enum class byte : unsigned char {};

};

Dzieje się tak, jeśli Twoja wersja C ++ nie ma std :: byte zdefiniuje typ bajtu w przestrzeni nazw std. Zwykle nie chcesz dodawać rzeczy do std, ale w tym przypadku brakuje standardowej rzeczy.

std :: byte z STL wykonuje znacznie więcej operacji.

Chris Reid
źródło