Czy bufor bajtów powinien być podpisany czy niepodpisany bufor znaków?

Czy bufor bajtów powinien być signed char lub unsigned char lub po prostu buforem char? Jakieś różnice między C i C++?

Dzięki.
Author: jackhab, 2009-03-17

14 answers

Czy powinien być podpisany bufor bajtów char lub unsigned char lub po prostu char bufor? Wszelkie różnice między C i C++?

Mała różnica w tym, jak język traktuje to. A Ogromna różnica w sposobie traktowania tego przez Konwencję.

  • char = ASCII (lub UTF-8, ale znaki tam przeszkadzają) tekstowe dane
  • unsigned char = bajt
  • signed char = rzadko używane

I jest kod, który opiera się na co za różnica. Zaledwie tydzień lub dwa temu napotkałem błąd, w którym dane JPEG były uszkodzone, ponieważ były przekazywane do wersji char* naszej funkcji kodowania Base64 - która " pomocnie "zastąpiła wszystkie nieprawidłowe UTF-8 W"string". Zmiana na BYTE aka unsigned char wystarczyła, aby to naprawić.

 30
Author: dan04,
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
2011-02-20 15:46:53

Jeśli zamierzasz przechowywać dowolne dane binarne, powinieneś użyć unsigned char. Jest to jedyny typ danych, który jest gwarantowany, że nie ma bitów wypełniających przez Standard C. Każdy inny typ danych może zawierać bity wypełniające w swojej reprezentacji obiektu(tzn. ten, który zawiera wszystkie bity obiektu, a nie tylko te, które określają wartość). Stan bitów wypełniających jest nieokreślony i nie jest używany do przechowywania wartości. Więc jeśli odczytasz za pomocą char jakieś dane binarne, rzeczy zostaną zredukowane do wartości zakres znaku (interpretując tylko bity wartości), ale nadal mogą istnieć bity, które są po prostu ignorowane, ale nadal istnieją i są odczytywane przez memcpy. Podobnie jak wypełnianie bitów w rzeczywistych obiektach struct. Gwarantujemy, że typ unsigned char nie będzie ich zawierał. To wynika z 5.2.4.2.1/2 (C99 TC2, n1124 tutaj):

Jeśli wartość obiektu typu char jest traktowana jako liczba całkowita podpisana, gdy jest używana w wyrażenie, wartość CHAR_MIN jest taka sama jak wartość SCHAR_MIN i wartość CHAR_MAX wynosi tak samo jak w SCHAR_MAX. W przeciwnym razie wartość CHAR_MIN wynosi 0, a wartość CHAR_MAX jest taka sama jak UCHAR_MAX. wartość UCHAR_MAX jest równa 2^CHAR_BIT − 1

Z ostatniego zdania wynika, że nie ma miejsca na żadne bity dopełniające. Jeśli używasz char jako typu bufora, masz również problem z przepełnieniem: przypisanie dowolnej wartości jawnie do jednego takiego elementu, który znajduje się w zakresie 8 bitów - więc możesz oczekiwać, że takie przypisanie będzie OK - ale nie w zakresie char, czyli CHAR_MIN..CHAR_MAX, taka konwersja przepełnia i powoduje implementację zdefiniowanych wyników, w tym podniesienie sygnałów.

Nawet jeśli jakiekolwiek problemy dotyczące powyższego prawdopodobnie nie pojawią się w rzeczywistych implementacjach (byłoby to Bardzo słaba jakość implementacji), najlepiej jest używać odpowiedniego typu Od początku, czyli unsigned char.

Dla łańcuchów, jednak typ danych wyboru to char, który będzie rozumiany przez funkcje string i print. Używanie signed char do tych celów wygląda mi na złą decyzję.

Aby uzyskać więcej informacji, przeczytaj this proposal które zawierają poprawkę dla następnej wersji standardu C, która ostatecznie będzie wymagała signed char nie ma również żadnych bitów wypełniających. Jest już włączone do working paper .

 47
Author: Johannes Schaub - litb,
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
2009-03-17 13:11:49

To zależy.

Jeśli bufor jest przeznaczony do przechowywania tekstu, to prawdopodobnie ma sens zadeklarować go jako tablicę char i pozwolić platformie zdecydować, czy jest on domyślnie podpisany czy niepodpisany. Spowoduje to na przykład najmniejsze problemy z przekazywaniem danych do i z biblioteki uruchomieniowej implementacji.

Jeśli bufor jest przeznaczony do przechowywania danych binarnych, to zależy od tego, jak zamierzasz go użyć. Na przykład, jeśli dane binarne są naprawdę spakowaną tablicą próbki danych, które są podpisane 8-bitowe pomiary ADC o stałych punktach, wtedy signed char byłoby najlepiej.

W większości przypadków, bufor jest tylko tym, buforem, a ty tak naprawdę nie dbasz o typy poszczególnych bajtów, ponieważ wypełniłeś bufor w operacji zbiorczej i masz zamiar przekazać go do parsera, aby zinterpretować złożoną strukturę danych i zrobić coś użytecznego. W takim przypadku zadeklaruj to w najprostszy sposób.

 12
Author: RBerteig,
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
2009-03-17 08:03:26

Jeśli rzeczywiście jest to bufor 8 bitów bajtów, a nie ciąg znaków w domyślnych ustawieniach regionalnych maszyny, użyłbym uint8_t. Nie jest tak, że istnieje wiele maszyn, w których znak nie jest bajtem (lub bajtem oktetem), ale stwierdzenie "to jest bufor oktetów "zamiast" to jest łańcuch " jest często użyteczną dokumentacją.

 9
Author: Pete Kirkham,
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
2009-03-17 09:49:02

Powinieneś użyć char lub unsigned char , ale nigdy signed char . Standard ma następujące w 3.9 / 2

Dla dowolnego obiektu (innego niż base-class subobject) typu POD T, czy obiekt posiada prawidłowa wartość typu T, bazowa bajtów (1.7) tworzących obiekt może być skopiowane do tablicy znaków lub unsigned char.Jeżeli zawartość tablica char lub unsigned char jest skopiowane z powrotem do obiektu, obiekt następnie przechowuje swój oryginalna wartość.

 5
Author: Richard Corden,
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
2009-03-17 11:08:26

Lepiej zdefiniować go jako unsigned char. W rzeczywistości bajt typu Win32 jest zdefiniowany jako znak niepodpisany. Nie ma różnicy między C i c++ między tym.

 4
Author: Naveen,
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
2009-03-17 08:01:18

Dla maksymalnej przenośności Zawsze używaj znaku unsigned. Istnieje kilka przypadków, w których może to wejść w grę. Serializowane dane współdzielone między systemami z różnymi typami endian natychmiast przychodzą na myśl. Podczas wykonywania shift lub bit maskowania wartości jest inny.

 3
Author: MrEvil,
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
2009-03-17 10:05:31

Wybór int8_t vs uint8_t jest podobny do porównania ptr jako NULL.


Z punktu widzenia funkcjonalności porównywanie z NULL jest takie samo jak porównywanie z 0, ponieważ NULL jest # define dla 0.

Ale osobiście, z punktu widzenia stylu kodowania, wybieram porównanie moich wskaźników do NULL, ponieważ null # define oznacza osobę utrzymującą kod, którą sprawdzasz pod kątem złego wskaźnika...

VS

Gdy ktoś widzi porównanie do 0 oznacza, że sprawdzasz określoną wartość.


Z powyższego powodu użyłbym uint8_t.

 2
Author: Trevor Boyd Smith,
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
2009-03-17 14:44:36

Jeśli pobierzemy element do szerszej zmiennej, będzie on oczywiście rozszerzony lub nie.

 0
Author: pngaz,
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
2009-03-17 07:55:25

Should I should ... Zazwyczaj preferuję unsigned, ponieważ jest to bardziej "surowe", mniej zachęcające do powiedzenia "hej, to tylko kilka małych ints", jeśli chcę podkreślić binarną zawartość danych.

Chyba nigdy nie użyłem jawnego signed char do reprezentowania bufora bajtów.

Oczywiście jedną trzecią opcji jest reprezentowanie bufora jako void * w jak największym stopniu. Wiele popularnych funkcji We/Wy działa z void *, Więc czasami decyzja, jakiego typu integer użyć, może być w pełni zamknięte, co jest miłe.

 0
Author: unwind,
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
2009-03-17 08:01:02

Kilka lat temu miałem problem z aplikacją konsolową C++, która drukowała kolorowe znaki dla wartości ASCII powyżej 128 i zostało to rozwiązane przez przełączenie z char na unsigned char, ale myślę, że było to rozwiązalne przy zachowaniu typu char.

Na razie większość funkcji C / C++ używa char i teraz rozumiem oba języki znacznie lepiej, więc używam char w większości przypadków.

 0
Author: schnaader,
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
2009-03-17 08:03:08

Naprawdę cię to obchodzi? Jeśli tego nie zrobisz, po prostu Użyj domyślnego znaku (char) i nie zaśmiecaj kodu nieistotną sprawą. W przeciwnym razie przyszli opiekunowie będą się zastanawiać, dlaczego użyłeś podpisanego (lub niepodpisanego). Ułatw im życie.

 0
Author: Gorpik,
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
2009-03-17 08:06:58

Jeśli skłamiesz kompilatorowi, ukarze cię to.

Jeśli bufor zawiera dane, które tylko przechodzą i nie będziesz nimi manipulować w żaden sposób, nie ma to znaczenia.

Jeśli jednak musisz operować na zawartości bufora, poprawna deklaracja typu ułatwi Ci kod. No" int val = buf[i] & 0xff; " nonsens.

Zastanów się więc, czym tak naprawdę są dane i jak je wykorzystać.

 -1
Author: Darron,
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
2009-03-17 14:57:30
typedef char byte;

Teraz możesz sprawić, że Twoja tablica będzie bytes. to oczywiste dla wszystkich, co miałeś na myśli, i nie tracisz żadnej funkcjonalności.

Wiem, że to trochę głupie, ale sprawia, że Twój kod czyta się w 100% tak, jak zamierzałeś.
 -1
Author: Matt Cruikshank,
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
2009-03-17 15:10:11