uint8_t vs unsigned char


231

Kullanmanın avantajı nedir uint8_tüzerine unsigned charC?

Neredeyse her sistemde uint8_tsadece bir typedef olduğunu biliyorum, unsigned charneden kullanıyorsunuz?

Yanıtlar:


225

Niyetinizi belgeliyor - bir karakter yerine küçük sayılar depolayacaksınız.

Ayrıca uint16_tveya gibi diğer typedef'ler kullanıyorsanız daha güzel görünüyor int32_t.


1
Standart bir tipten bahsediyorsak orijinal soruda net değildi. Eminim yıllar içinde bu isimlendirme sözleşmesinin birçok varyasyonu vardır.
Mark Ransom

8
Niyetleri açıkça kullanarak unsigned charveya signed charbelgelendirdiğiniz için, süslenmemiş charkarakterler ile çalıştığınızı gösterir.
caf

9
Ben sade bir düşünce unsignedidi unsigned inttanım gereği?
Mark Ransom

5
@endolith, bir dize için uint8_t kullanmak her zaman yanlış değildir, ama kesinlikle tuhaftır.
Mark Ransom

5
@endolith, UTF8 metin ile uint8_t için bir dava yapabilir düşünüyorum. Gerçekten de, charbir karakter anlamına gelirken, UTF8 dizesi bağlamında, çok baytlı bir karakterin sadece bir baytı olabilir. Uint8_t kullanmak, her konumda bir karakter beklememesi gerektiğini açıkça ifade edebilir - diğer bir deyişle, string / dizinin her elemanının herhangi bir anlamsal varsayım yapmaması gereken keyfi bir tamsayı olduğu anlaşılabilir. Elbette tüm C programcıları bunu biliyor, ancak yeni başlayanları doğru soruları sormaya zorlayabilir.
tne

70

Sadece bilgiçlikçi olmak için, bazı sistemlerde 8 bitlik bir tip olmayabilir. Wikipedia'ya göre :

N = 8, 16, 32 veya 64 için tam genişlikli tamsayı türlerini tanımlamak ve yalnızca gereksinimleri karşılayan herhangi bir türü varsa bir uygulama gereklidir. Uygun tipleri desteklese bile bunları başka N için tanımlamanız gerekmez.

Bu nedenle var uint8_tolduğu garanti edilmez, ancak 8 bit = 1 bayt olan tüm platformlar için geçerli olacaktır. Bazı gömülü platformlar farklı olabilir, ancak bu çok nadir görülür. Bazı sistemler chartürleri 16 bit olarak tanımlayabilir , bu durumda muhtemelen 8 bitlik bir tür olmayacaktır.

Bu (küçük) sorun dışında, @Mark Ransom'un cevabı bence en iyisidir. Verileri ne için kullandığınızı en açık şekilde göstereni kullanın.

Ayrıca, (herhangi bir standardın parçası değil ) yerine ( başlıkta uint8_tsağlanan C99 standart typedef) demek istediğinizi varsayıyorum .stdint.huint_8


3
@caf, tamamen meraktan - bazı açıklamalara bağlantı verebilir misiniz? Ben var biri biliyorum çünkü biri (ve bunun için geliştirici dokümanlar ile bağlantılı) bir comp.lang.c ++. Yönetilen tartışma C / C ++ türü garanti çok zayıf olup olmadığını, ama artık bu konu bulamıyorum ve her zaman kullanışlı benzer tartışmalarda referans için :)
Pavel Minaev

3
"Bazı sistemler karakter türlerini 16 bit olarak tanımlayabilir, bu durumda 8 bitlik bir tür olmayacaktır." - ve benden bazı yanlış itirazlarına rağmen Pavel karakter 16 bit ise, bu durumda derleyici bir 8 bitlik türü sağlamaz bile, o onun cevabını göstermiştir olmamalıdır diyoruz uint8_t(veya buna buna typedef). Bunun nedeni, 8 bit türünün depolama gösteriminde kullanılmaması gereken bitlere uint8_tsahip olmasıdır.
Steve Jessop

3
SHARC mimarisinde 32 bit sözcük vardır. Ayrıntılar için en.wikipedia.org/wiki/… adresine bakın.
BCran

2
Ve TI'nin (OMAP1 ve OMAP2'de bulunan) C5000 DSP'leri 16bit'tir. Bence OMAP3 için 8 bitlik bir karakterle C6000 serisine gittiler.
Steve Jessop

4
N3242'ye kazmak - "Çalışma Taslağı, C ++ Programlama Standardı", bölüm 18.4.1 <cstdint> sinopsis diyor - typedef unsigned integer type uint8_t; // optional Yani, aslında, uint8_t'yi tanımlamak için C ++ standart uygun bir kütüphaneye hiç gerek yok (açıklamaya bakınız // isteğe bağlı )
nightlytrails

43

Bütün mesele, uygulamadan bağımsız kod yazmaktır. unsigned char8 bitlik bir tip olduğu garanti edilmez. uint8_t(varsa).


4
... eğer bir sistemde mevcutsa, ama bu çok nadir olacak. +1
Chris Lutz

2
Eğer kodunuzda bir sistemde derlenmeme konusunda gerçekten sorun yaşadıysanız uint8_t mevcut değilse, uint8_t'nin tüm oluşumlarını otomatik olarak imzasız karakter veya sizin için daha yararlı bir şeyle değiştirmek için find ve sed'i kullanabilirsiniz.
bazz

2
@bazz - 8 bitlik bir tür olduğunu düşünmüyorsanız, örneğin uzak bir sistem tarafından yavaşça paketlenmiş verileri açmak için. Örtülü varsayım, uint8_t değerinin var olmamasının bir karakterin 8 bit'ten fazla olduğu bir işlemcide olmasıdır.
Chris Stratton

iddia beyanı atmak (sizeof (unsigned char) == 8);
bazz

3
@bazz yanlış iddiası korkarım. 1 bayt sizeof(unsigned char)dönecektir 1. ancak eğer bir sistem karakteri ve int aynı boyutta, örneğin 16 bit ise, o sizeof(int)zaman geri dönecektir1
Toby

7

Dediğiniz gibi, " neredeyse her sistem".

charmuhtemelen değişme olasılığı daha azdır, ancak kullanmaya başladığınızda uint16_tve arkadaşlarınızla uint8_tkarışımları daha iyi kullanmak ve hatta bir kodlama standardının parçası olabilir.


7

Deneyimlerime göre uint8_t'yi 8 bit (ve uint16_t, vb.) Olarak kullanmak istediğimiz ve 8 bit'ten daha küçük alanlara sahip olabileceğimiz iki yer var. Her iki yer de alanın önemli olduğu yerlerdir ve hata ayıklama sırasında genellikle verilerin ham bir dökümünden bakmamız ve neyi temsil ettiğini hızlı bir şekilde belirleyebilmemiz gerekir.

Birincisi RF protokollerinde, özellikle dar bant sistemlerinde. Bu ortamda tek bir mesajda olabildiğince fazla bilgi toplamamız gerekebilir. İkincisi, çok sınırlı alana sahip olabileceğimiz flash depolamadadır (gömülü sistemlerde olduğu gibi). Her iki durumda da, derleyicinin bizim için paketleme ve ambalajı açacağı paketlenmiş bir veri yapısı kullanabiliriz:

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

Hangi yöntemi kullandığınız derleyicinize bağlıdır. Aynı başlık dosyalarına sahip birkaç farklı derleyiciyi de desteklemeniz gerekebilir. Bu, cihazların ve sunucuların tamamen farklı olabileceği gömülü sistemlerde olur - örneğin, bir x86 Linux sunucusuyla iletişim kuran bir ARM cihazınız olabilir.

Paketlenmiş yapıları kullanan birkaç uyarı vardır. En büyük sorun, bir üyenin adresini kayıttan çıkarmaktan kaçınmanızdır. Mutibyte hizalanmış kelimelere sahip sistemlerde, bu yanlış hizalanmış bir istisna ve bir coredump ile sonuçlanabilir.

Bazı insanlar da performans konusunda endişelenecek ve bu paketlenmiş yapıları kullanmanın sisteminizi yavaşlatacağını savunacaklardır. Sahne arkasında, derleyicinin hizalanmamış veri üyelerine erişmek için kod eklediği doğrudur. Bunu IDE'nizdeki montaj koduna bakarak görebilirsiniz.

Ancak, paketlenmiş yapılar iletişim ve veri depolama için en yararlı olduğu için, veriler bellekte çalışırken paketlenmemiş bir gösterime çıkarılabilir. Normalde yine de bellekteki tüm veri paketiyle çalışmamız gerekmez.

İşte bazı ilgili tartışmalar:

pragma paketi (1) veya __attribute__ ((hizalanmış (1))) çalışır

Gcc'nin __attribute __ ((paketli)) / #pragma paketi güvensiz mi?

http://solidsmoke.blogspot.ca/2010/07/woes-of-structure-packing-pragma-pack.html


6

Çok az. Taşınabilirlik bakış açısından, char8 bitten daha küçük olamaz ve hiçbir şey bundan daha küçük olamaz char, bu nedenle belirli bir C uygulaması işaretsiz 8 bitlik bir tamsayı türüne sahipse, öyle olacaktır char. Alternatif olarak, hiç bir typedefhilesi olmayabilir, bu noktada herhangi bir numara hiledir.

Kodunuzu orada 8 bit bayt ve başka bir şeye ihtiyacınız olmadığı açık bir şekilde daha iyi belgelemek için kullanılabilir. Ancak pratikte zaten neredeyse her yerde makul bir beklenti var (bunun doğru olmadığı DSP platformları var, ancak kodunuzun çalışma şansı zayıf ve programınızın üstünde statik bir iddia kullanarak hata yapabilirsiniz. böyle bir platform).


7
@Skizz - Hayır, standardın unsigned char0 ile 255 arasında değerleri tutabilmesi gerekir . Bunu 4 bitte yapabiliyorsanız şapkam size kapalıdır.
Chris Lutz

1
"Biraz daha hantal olurdu" - derleyici yazarın olduğu yere kadar yürümeniz (yüzmeniz, bir uçak yakalamanız vb.) anlamında hantal, onları başınızın arkasına tokatlayın ve uint8_tuygulamaya ekleme yapmalarını sağlayın . Merak ediyorum, 16 bit karakterli DSP'ler için derleyiciler genellikle uygulanıyor uint8_tmu uygulanmıyor mu?
Steve Jessop

6
Bu arada, ikinci bir düşüncede, "Gerçekten 8 bite ihtiyacım var" demenin #include <stdint.h>ve kullanmanın belki de en basit yoludur uint8_t. Platformda varsa, size verecektir. Platformda yoksa, programınız derlenmeyecek ve nedeni açık ve anlaşılır olacaktır.
Pavel Minaev

2
Hala puro yok, özür dilerim: "İmzasız karakter dışındaki imzasız tamsayı türleri için, nesne gösteriminin bitleri iki gruba ayrılacaktır: değer bitleri ve dolgu bitleri ... N değeri bitleri varsa, her bit farklı bir 2 ve 1 ^ 2 (N-1) arasındaki güç, böylece bu tür nesneler saf bir ikili gösterim kullanarak 0 ile 2 ^ (N-1) arasındaki değerleri temsil edebileceklerdir ... intedef_t tür tanımlaması işaretli tam sayı türü, genişlik N, dolgu biti ve ikisinin tamamlayıcı gösterimi. "
Pavel Minaev

1
Sadece aritmetik moduloya ihtiyacınız varsa, imzasız bit alanı gayet iyi olacaktır (eğer uygunsuzsa). Diyelim ki, dolgu içermeyen bir dizi oktete ihtiyacınız var, o zaman SOL'sunuz. Hikayenin ahlakı DSP'leri kodlamak değil, doğru, Tanrı'ya dürüst-8 bitlik char mimarilerine sadık kalmak değil :)
Pavel Minaev

4

Bu, örneğin bir ağ analizörü yazarken gerçekten önemlidir. paket başlıkları, belirli bir platformun C derleyicisinin çalışma şekliyle değil, protokol belirtimi ile tanımlanır.


Ben bunu sorduğumda seri üzerinden iletişim için basit bir protokol tanımlanmıştı.
Lyndon White

2

Hemen hemen her sistemde uint8_t == imzasız karakter ile tanıştım, ancak bu C standardı tarafından garanti edilmiyor. Taşınabilir kod yazmaya çalışıyorsanız ve belleğin tam olarak ne büyüklükte olduğu konusunda uint8_t kullanın. Aksi takdirde imzasız karakter kullanın.


3
uint8_t 8 bit unsigned charolduğunda her zaman aralığını ve boyutunu ve dolgu (hiçbiri) ile eşleşir unsigned char. Ne zaman unsigned char8 bit değil, uint8_tyok.
chux - Monica

@chux, Standartta söylediği yerle ilgili bir referansınız var mı? Eğer unsigned char8-bit edilir uint8_tbir olmasını garanti typedefbunların bir typedefbir bölgesinin genişletilmiş tamsayı türü ?
hsivonen

@hsivonen "Bunu söylediği standartta kesin yer?" -> Hayır - henüz 7.20.1.1'e bakınız. En unsigned char/signed char/charküçük tipte olduğu gibi kolayca çıkarılır - 8 bitten daha az olmamalıdır. unsigned chardolgu yok. For uint8_tolması için, 8-bit, dolgu yok olmalı, çünkü bir uygulama sağlanan türü tamsayı bulunmaktadır: minimal şartları uyan unsigned char. "... bir typedef olması garanti ..." gelince göndermek için iyi bir soru gibi görünüyor.
chux - Monica adlı kişiyi geri yükle
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.