C / C ++ 'da ne için unsigned char
kullanılır? Normalden farkı char
nedir?
C / C ++ 'da ne için unsigned char
kullanılır? Normalden farkı char
nedir?
Yanıtlar:
C ++ 'da üç farklı karakter türü vardır:
char
signed char
unsigned char
Metin için karakter türleri kullanıyorsanız, nitelenmemiş olanı kullanın char
:
'a'
veya gibi karakter değişmezleri türüdür '0'
."abcde"
Ayrıca bir sayı değeri olarak da çalışır, ancak bu değerin imzalı veya imzasız olarak muamele görüp görmediği belirtilmez. Eşitsizlikler yoluyla karakter karşılaştırmalarına dikkat edin - kendinizi ASCII (0-127) ile sınırlarsanız, hemen hemen güvende olursunuz.
Karakter türlerini sayı olarak kullanıyorsanız , şunu kullanın:
signed char
size en az -127 ila 127 aralığı verir. (-128 ila 127 yaygındır)unsigned char
, bu da size en az 0 ila 255 aralığı verir."En azından", çünkü C ++ standardı yalnızca her sayısal türün kapsaması için gereken minimum değerleri verir. sizeof (char)
1 (yani bir bayt) olmalıdır, ancak bir bayt teorik olarak örneğin 32 bit olabilir. sizeof
yine de boyutunu1
- sahip olabileceğiniz anlamına gelir sizeof (char) == sizeof (long) == 1
.
sizeof
Bir işlev değil, bir işleç olduğu için daha sonra boşluk bırakmak yaygındır . Bir değişkenin boyutunu alırken parantezin atlanması daha iyi bir stildir. sizeof *p
veya sizeof (int)
. Bu, bir tür veya değişken için geçerliyse hızlı bir şekilde netleştirir. Aynı şekilde parantez koymak da gereksizdir return
. Bu bir işlev değil.
char
: 'a'
veya gibi karakter değişmezlerinin türüdür '0'
." C ++ 'da doğrudur ancak C değil. C' 'a'
de bir int
.
Bu, C standardının imzasını tanımlamadığı için uygulamaya bağlıdır char
. Platforma bağlı olarak, karakter olabilir signed
veya unsigned
açıkça sormak gerekir, böylece signed char
ya unsigned char
da uygulama buna bağlıdır eğer. char
Dizelerin karakterlerini temsil etmek istiyorsanız kullanın , çünkü bu platformunuzun dizeye koyduğu değerle eşleşir.
Arasındaki fark signed char
ve unsigned char
beklediğiniz gibi olduğunu. En platformlarında, signed char
arasında değişen bir 8-bit ikinin tümleyici numarası olacaktır -128
için 127
, ve unsigned char
(8-bit işaretsiz bir tamsayı olacaktır 0
için 255
). Standart, char
tiplerin 8 bit içermesini GEREKMEZ , sadece bu sizeof(char)
dönüşü gerektirdiğini unutmayın 1
. Sen bir char bit numaradan alabilirsiniz CHAR_BIT
içinde limits.h
. Bununla birlikte, bugün bunun dışında bir şey olacağı birkaç platform var 8
.
Burada bu sorunun güzel bir özeti var .
Diğerleri bunu gönderdiğimden beri söylediğim gibi, kullanmaktan daha iyidir int8_t
ve uint8_t
gerçekten küçük tam sayıları temsil etmek istiyorsanız.
CHAR_BIT
standart tarafından en az 8 bit olmalıdır.
Gerçekten çağırıldığını hissediyorum çünkü, sadece C ve C ++ bazı kurallarını belirtmek istiyorum (bu konuda aynıdır). İlk olarak, tüm bitler arasında unsigned char
değer herhangi bir işaretsiz karakter nesne olmadığını belirlemede katılabilir. İkincisi, unsigned char
açıkça imzasız olarak belirtilir.
Şimdi, -1
int türünün değerini dönüştürdüğünüzde ne olacağı hakkında biriyle görüştüm unsigned char
. Elde edilen sonucun unsigned char
tüm bitlerinin 1'e ayarlandığı fikrini reddetti , çünkü işaret gösterimi konusunda endişeliydi. Ama zorunda değil. Dönüşümün amaçlananı yaptığı hemen bu kuralın dışına çıkar:
Yeni tür imzasızsa, değer, yeni türün aralığına gelinceye kadar, yeni türde temsil edilebilecek maksimum değerden bir kez daha fazla eklenerek veya çıkarılarak dönüştürülür. (
6.3.1.3p2
C99 taslağında)
Bu matematiksel bir açıklama. C ++, aynı kuralı veren modulo hesabı açısından açıklar. Neyse, olan olmayan garantili tamsayı tüm bitleri olmasıdır -1
dönüşümden önce biridir. Peki, sonuçta unsigned char
tüm CHAR_BIT
bitlerinin 1'e döndüğünü iddia edebilmek için neye sahibiz ?
UCHAR_MAX+1
için -1
, yani, aralığı içinde bir değere verecektirUCHAR_MAX
Aslında bu yeterli! Bu yüzden unsigned char
tüm bitlerine sahip olmak istediğinizde ,
unsigned char c = (unsigned char)-1;
Ayrıca, bir dönüşümün yalnızca yüksek dereceli bitleri kısaltmak olmadığı da anlaşılmaktadır. İkisinin tamamlayıcısı için şanslı olay , bunun sadece bir kısaltma olması, ancak aynı durumun diğer işaret gösterimleri için mutlaka doğru olmamasıdır.
UCHAR_MAX
?
(unsigned type)-1
bir tür deyim. ~0
değil.
int x = 1234
ve char *y = &x
. İkili temsil 1234
DİR 00000000 00000000 00000100 11010010
. Makinem biraz endian, bu yüzden tersine çevirir ve 11010010 00000100 00000000 00000000
LSB belleğinde saklanır . Şimdi Ana Bölüm. eğer kullanırsam printf("%d" , *p)
. printf
İlk bayt okuyacaktır 11010010
çıkıştır -46
ama 11010010
olan 210
bu baskı yok neden bu kadar -46
. Ben tam anlamıyla bazı char bir şey yapıyor sanırım gerçekten kafam karıştı ama bilmiyorum.
Örneğin imzasız karakter kullanımı gibi :
unsigned char
genellikle her renk bileşenine tek bir bayt atayan (her zaman olmasa da) bilgisayar grafiklerinde kullanılır. Her biri 24 (veya 32) bit olarak temsil edilen bir RGB (veya RGBA) rengini görmek yaygındır unsigned char
. Yana unsigned char
değerlerin aralığında [0255] düşmesi, değerleri tipik olarak yorumlanır:
Böylece (255,0,0) -> (% 100 kırmızı,% 0 yeşil,% 0 mavi) olarak RGB kırmızısı elde edersiniz.
Neden a kullanmıyorsunuz signed char
? Aritmetik ve bit kaydırma problemli hale gelir. Daha önce açıklandığı gibi, bir signed char
aralığı esasen -128 ile değiştirilir. RGB'yi gri tonlamaya dönüştürmek için çok basit ve naif (çoğunlukla kullanılmayan) bir yöntem, üç renk bileşeninin tümünü ortalamaktır, ancak renk bileşenlerinin değerleri negatif olduğunda bu sorunlara yol açar. unsigned char
Aritmetik kullanılırken kırmızı (255, 0, 0) ortalaması (85, 85, 85) olur . Ancak, değerler signed char
s (127, -128, -128) olsaydı, alanımızda (29, 29, 29) olan (-99, -99, -99) ile sonuçlanırdık unsigned char
, bu da yanlış .
Bir karakteri küçük bir tamsayı olarak kullanmak istiyorsanız, bunu yapmanın en güvenli yolu int8_t
ve uint8_t
türleridir.
int8_t
ve uint8_t
isteğe bağlıdır ve bayt boyutunun tam olarak 8 bit olmadığı mimarilerde tanımlanmamıştır. Tersine, signed char
ve unsigned char
her zaman kullanılabilir ve en az 8 bit tutma garantisi vardır. Ortak bir yol olabilir, ancak en güvenli yöntem olmayabilir .
signed char
ve unsigned char
? Yoksa bu durumda daha iyi bir "daha güvenli" alternatif tavsiye eder misiniz? Örneğin, "gerçek" tamsayı türlerine bağlı kalmak signed int
ve unsigned int
bunun yerine bir nedenden dolayı?
signed char
ve unsigned char
ile uyumlu tüm uygulamalar için taşınabilir ve depolama alanından tasarruf sağlar ancak bazı kod boyutu artışlarına neden olabilir. Bazı durumlarda, küçük değerleri bit alanlarında veya normal tamsayı türlerinin tek bitlerinde depolayarak daha fazla depolama alanı tasarrufu sağlar. Bu sorunun kesin bir cevabı yoktur, bu yaklaşımın uygunluğu eldeki özel duruma bağlıdır. Ve bu cevap zaten soruyu ele almıyor.
char
ve unsigned char
tüm platformlarda 8 bit tür olduğu garanti edilmez; bunların 8 bit veya daha büyük olduğu garanti edilir. Bazı platformlarda 9 bit, 32 bit veya 64 bit bayt bulunur . Ancak, bugün en yaygın platformlarda (Windows, Mac, Linux x86 vb.) 8 bit bayt vardır.
signed char
-128 ila 127 aralığındadır; unsigned char
0 ila 255 aralığındadır.
char
derleyiciye bağlı olarak imzalı karakter veya imzasız karaktere eşdeğer olacaktır, ancak farklı bir türdür.
C tarzı dizeler kullanıyorsanız, kullanın char
. Aritmetik (oldukça nadir) için karakter kullanmanız gerekiyorsa, taşınabilirlik için imzalı veya imzasız olarak açıkça belirtin.
An unsigned char
, işaretsiz bir bayt değeridir (0 ila 255). char
Bir "karakter" olarak düşünüyor olabilirsiniz, ama bu gerçekten sayısal bir değerdir. Normal char
imzalanmıştır, bu nedenle 128 değeriniz vardır ve bu değerler ASCII kodlamasını kullanan karakterlerle eşleşir. Ancak her iki durumda da, bellekte sakladığınız şey bir bayt değeridir.
Doğrudan değerler açısından, değerlerin arasında olduğu bilindiğinde CHAR_MIN
ve CHAR_MAX
imzasız bir karakter pozitif uçtaki aralığı iki katına çıkarırken normal bir karakter kullanılır . Örneğin CHAR_BIT
, 8 ise , normal aralığın char
yalnızca [0, 127] olduğu (çünkü imzalanabileceği veya imzalanabileceği) unsigned char
[0, 255] ve signed char
[-127, 127] olacağı garanti edilir .
Ne için kullanıldıkları açısından, standartlar POD (düz eski veriler) nesnelerinin doğrudan işaretsiz karakter dizisine dönüştürülmesine izin verir. Bu, nesnenin temsilini ve bit desenlerini incelemenizi sağlar. Char veya imzalı char için aynı güvenli tip çiftçilik garantisi yoktur.
unsigned char
değil, bir dizi spesifik olarak, herhangi bir "dönüşüm", sadece resmi ile tanımlanır kopyalama bir gerçek nesneden, ilan dizi arasında unsigned char
ve daha sonra, sözkonusu kontrol. OR'nin böyle bir dizi olarak doğrudan yeniden yorumlanıp yorumlanamayacağı açık değildir, işaretçi aritmetiği için ödeneklerle, yani ==
bu kullanımda "dizi" "dizisi" olup olmadığı açık değildir . Bunun açıklığa kavuşturulması umuduyla # 1701 numaralı bir Temel Sorun var. Neyse ki, bu belirsizlik beni son zamanlarda gerçekten rahatsız ediyor.
unsigned char
++ptr
memcpy
unsigned char
tüm bitlerin kalbidir. ALL platformu için neredeyse ALL derleyicisinde, an unsigned char
sadece küçük bir tamsayı veya bir bit paketi olarak işlenebilen bir bayt ve imzasız (genellikle) 8 bitlik bir tamsayıdır.
Bağımlılıkta, başka birinin söylediği gibi, standart bir karakterin işaretini tanımlamaz. Böylece 3 ayrı olması char
türleri: char
, signed char
, unsigned char
.
Belirli uzunluk ve signedness çeşitli kullanmak gibi, muhtemelen daha iyi durumda olan iseniz uint8_t
, int8_t
, uint16_t
vb yaptıkları çünkü onlar dediklerimi.
Bazı bulundu googling bu kişiler bu hakkında bir tartışma vardı nerede.
İmzasız bir karakter temelde tek bir bayttır. Bu nedenle, bir bayt veriye ihtiyacınız varsa bunu kullanırsınız (örneğin, genellikle Windows API'da yapıldığı gibi bir işleve geçirilecek bayrakları açmak ve kapatmak için kullanmak isteyebilirsiniz).
İmzasız bir karakter, normal bir karakterin işareti için ayrılan biti başka bir sayı olarak kullanır. Bu, aralığı [-128 - 127] yerine [0 - 255] olarak değiştirir.
Bir işaret istemediğinizde genellikle işaretsiz karakterler kullanılır. Bu, bir karakter ile sayı olarak kullanmak yerine bayt olarak uğraşırken, bitleri değiştirmek (kaydırma işareti uzatır) ve diğer şeyleri yaparken bir fark yaratacaktır.
alıntı frome "c programlama laugage" kitap:
Niteleyici signed
veya unsigned
kömür ya da herhangi bir tam sayı tatbik edilebilir. imzasız sayılar her zaman pozitif veya sıfırdır ve aritmetik modulo 2 ^ n yasalarına uyun; burada n, türdeki bit sayısıdır. Örneğin, eğer karakter 8 bit ise, imzasız karakter değişkenleri 0 ile 255 arasında değerlere sahipken, imzalı karakterlerin değeri -128 ile 127 arasındadır (iki tamamlayıcı makinede.) Düz karakterlerin imzalı veya imzasız olup olmadığı makinedir. bağımsız, ancak yazdırılabilir karakterler her zaman pozitiftir.
signed char
ve unsigned char
her ikisi de 1baytı temsil eder, ancak farklı aralıkları vardır.
Type | range
-------------------------------
signed char | -128 to +127
unsigned char | 0 to 255
Gelen signed char
düşündüğümüz takdirde char letter = 'A'
, 'A' içinde 65 ikili temsil olduğu ASCII/Unicode
65 saklanabilir ise, -65 da saklanabilir. ASCII/Unicode
Negatif değerler için endişelenmenize gerek olmadığı için orada negatif ikili değerler yoktur.
Misal
#include <stdio.h>
int main()
{
signed char char1 = 255;
signed char char2 = -128;
unsigned char char3 = 255;
unsigned char char4 = -128;
printf("Signed char(255) : %d\n",char1);
printf("Unsigned char(255) : %d\n",char3);
printf("\nSigned char(-128) : %d\n",char2);
printf("Unsigned char(-128) : %d\n",char4);
return 0;
}
Çıktı -:
Signed char(255) : -1
Unsigned char(255) : 255
Signed char(-128) : -128
Unsigned char(-128) : 128