Wat is het voordeel van het gebruik van uint8_t
ten opzichte van unsigned char
in C?
Ik weet dat op bijna elk systeem uint8_t
slechts 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_t
of 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_t
bestaat 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_t
bedoelde (de standaard typedef van C99 in de stdint.h
header) 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 char
is niet gegarandeerd een 8-bits type. uint8_t
is (indien beschikbaar).
Antwoord 4, Autoriteit 4%
Zoals u zei, “bijna elk systeem”.
char
is waarschijnlijk een van minder kans om te veranderen, maar zodra u begint met het gebruik van uint16_t
en vrienden, met behulp van uint8_t
Better, 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 char
niet 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.