uint8_t vs unsigned char

Wat is het voordeel van het gebruik van uint8_tten opzichte van unsigned charin C?

Ik weet dat op bijna elk systeem uint8_tslechts een typedef is voor unsigned char,
dus waarom zou je het gebruiken?


Antwoord 1, autoriteit 100%

Het documenteert je intentie – je slaat kleine getallen op in plaats van een teken.

Het ziet er ook mooier uit als je andere typedefs gebruikt, zoals uint16_tof int32_t.


Antwoord 2, autoriteit 32%

Om pedant te zijn, sommige systemen hebben mogelijk geen 8-bits type. Volgens Wikipedia:

Er is een implementatie vereist om integer-typen met exacte breedte te definiëren voor N = 8, 16, 32 of 64 als en alleen als het een type heeft dat aan de vereisten voldoet. Het is niet nodig om ze voor een andere N te definiëren, zelfs als deze de juiste typen ondersteunt.

Dus uint8_tbestaat niet gegarandeerd, hoewel dit wel het geval is voor alle platforms waar 8 bits = 1 byte. Sommige embedded platforms kunnen anders zijn, maar dat wordt zeer zeldzaam. Sommige systemen kunnen char-typen definiëren als 16 bits, in welk geval er waarschijnlijk geen 8-bits type zal zijn.

Anders dan dat (kleine) probleem, @Mark Ransom’s antwoordis naar mijn mening de beste. Gebruik degene die het duidelijkst laat zien waarvoor u de gegevens gebruikt.

Ik neem ook aan dat je uint8_tbedoelde (de standaard typedef van C99 in de stdint.hheader) in plaats van uint_8(geen onderdeel van een standaard).


Antwoord 3, autoriteit 21%

Het hele punt is om implementatie-onafhankelijke code te schrijven. unsigned charis niet gegarandeerd een 8-bits type. uint8_tis (indien beschikbaar).


Antwoord 4, Autoriteit 4%

Zoals u zei, “bijna elk systeem”.

charis waarschijnlijk een van minder kans om te veranderen, maar zodra u begint met het gebruik van uint16_ten vrienden, met behulp van uint8_tBetter, en kan zelfs deel uitmaken van een codeerstandaard.


Antwoord 5, Autoriteit 3%

In mijn ervaring zijn er twee plaatsen waar we Uint8_T willen gebruiken om 8 bits (en uint16_t, enz.) En waar we velden kleiner dan 8 bits kunnen hebben. Beide plaatsen zijn waar ruimte is en we moeten vaak naar een onbewerkte dump van de gegevens kijken bij het debuggen en moeten snel bepalen wat het vertegenwoordigt.

De eerste is in RF-protocollen, vooral in smalle-bandsystemen. In deze omgeving moeten we mogelijk zoveel mogelijk informatie inpakken als we kunnen in een enkel bericht. De tweede is in flash-opslag waar we misschien een zeer beperkte ruimte hebben (zoals in embedded systemen).
In beide gevallen kunnen we een ingepakte gegevensstructuur gebruiken waarin de compiler voor de verpakking zorgt en voor ons uitpakken:

#pragma pack(1)
typedef struct {
  uint8_t    flag1:1;
  uint8_t    flag2:1;
  padding1   reserved:6;  /* not necessary but makes this struct more readable */
  uint32_t   sequence_no;
  uint8_t    data[8];
  uint32_t   crc32;
} s_mypacket __attribute__((packed));
#pragma pack()

Welke methode die u gebruikt, is afhankelijk van uw compiler. Mogelijk moet u ook verschillende compilers ondersteunen met dezelfde header-bestanden. Dit gebeurt in embedded systemen waar apparaten en servers volledig verschillend kunnen zijn – bijvoorbeeld kunt u een arm-apparaat hebben dat communiceert met een X86 Linux-server.

Er zijn een paar voorbeeldingen met het gebruik van verpakte structuren. De grootste gotcha is dat u moet vermijden Deleferencing het adres van een lid. Op systemen met afgestemde woorden van mutibyten, kan dit resulteren in een verkeerd uitgelijnde uitzondering – en een Coredump.

Sommige mensen zullen zich ook zorgen maken over de prestaties en beweren dat het gebruik van deze verpakte structuren uw systeem vertraagt. Het is waar dat achter de schermen de compiler code toevoegt om de niet-gealigneerde gegevenselementen te openen. U kunt zien door naar de assemblagecode in uw IDE te kijken.

Maar aangezien ingepakte structuren het meest bruikbaar zijn voor communicatie- en gegevensopslag, kunnen de gegevens worden geëxtraheerd in een niet-verpakte weergave bij het werken in het geheugen.
Normaal hoeven we toch niet met het volledige gegevenspakket in het geheugen te werken.

Hier is enkele relevante discussie:

Pragma-pack (1) noch __attribute__ ((uitgelijnd (1))) Werkt

is GCC’s __attribute __ ((verpakt)) / #pragma pack onveilig?

http: //solidsmoke.blogspot .ca / 2010/07 / woe’s-of-structuur-packing-pragma-pack.html


Antwoord 6, Autoriteit 2%

Er is weinig. Vanuit het oogpunt van draagbaarheid kan charniet kleiner zijn dan 8 bits, en niets kan kleiner zijn dan char, dus als een gegeven C-implementatie een niet-ondertekend 8-bits integer type heeft, is het wordt char. Het kan ook zijn dat het er helemaal geen heeft, en op dat moment zijn alle typedef-trucs overbodig.

Het zou kunnen worden gebruikt om uw code beter te documenteren in die zin dat het duidelijk is dat u daar 8-bits bytes nodig heeft en niets anders. Maar in de praktijk is het vrijwel overal al een redelijke verwachting (er zijn DSP-platforms waarop het niet waar is, maar de kans dat uw code daar wordt uitgevoerd is klein, en u kunt net zo goed fouten maken met een statische bewering bovenaan uw programma op zo’n platform).


Antwoord 7, autoriteit 2%

Dat is bijvoorbeeld erg belangrijk als je een netwerkanalysator schrijft.
pakketheaders worden gedefinieerd door de protocolspecificatie, niet door de manier waarop de C-compiler van een bepaald platform werkt.


Antwoord 8

Op bijna elk systeem dat ik heb ontmoet uint8_t == unsigned char, maar dit wordt niet gegarandeerd door de C-standaard. Als u draagbare code probeert te schrijven en het precies uitmaakt hoe groot het geheugen is, gebruikt u uint8_t. Gebruik anders niet-ondertekende tekens.

Other episodes