C / C ++ 'da ne için unsigned charkullanılır? Normalden farkı charnedir?
C / C ++ 'da ne için unsigned charkullanılır? Normalden farkı charnedir?
Yanıtlar:
C ++ 'da üç farklı karakter türü vardır:
charsigned charunsigned charMetin 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 charsize 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. sizeofyine de boyutunu1 - sahip olabileceğiniz anlamına gelir sizeof (char) == sizeof (long) == 1.
sizeofBir 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 *pveya 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 signedveya unsignedaçıkça sormak gerekir, böylece signed charya unsigned charda uygulama buna bağlıdır eğer. charDizelerin karakterlerini temsil etmek istiyorsanız kullanın , çünkü bu platformunuzun dizeye koyduğu değerle eşleşir.
Arasındaki fark signed charve unsigned charbeklediğiniz gibi olduğunu. En platformlarında, signed chararasında değişen bir 8-bit ikinin tümleyici numarası olacaktır -128için 127, ve unsigned char(8-bit işaretsiz bir tamsayı olacaktır 0için 255). Standart, chartiplerin 8 bit içermesini GEREKMEZ , sadece bu sizeof(char)dönüşü gerektirdiğini unutmayın 1. Sen bir char bit numaradan alabilirsiniz CHAR_BITiç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_tve uint8_tgerçekten küçük tam sayıları temsil etmek istiyorsanız.
CHAR_BITstandart 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 chardeğer herhangi bir işaretsiz karakter nesne olmadığını belirlemede katılabilir. İkincisi, unsigned charaçıkça imzasız olarak belirtilir.
Şimdi, -1int 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 chartü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.3p2C99 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 -1dönüşümden önce biridir. Peki, sonuçta unsigned chartüm CHAR_BITbitlerinin 1'e döndüğünü iddia edebilmek için neye sahibiz ?
UCHAR_MAX+1için -1, yani, aralığı içinde bir değere verecektirUCHAR_MAXAslında bu yeterli! Bu yüzden unsigned chartü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)-1bir tür deyim. ~0değil.
int x = 1234ve char *y = &x. İkili temsil 1234 DİR 00000000 00000000 00000100 11010010. Makinem biraz endian, bu yüzden tersine çevirir ve 11010010 00000100 00000000 00000000LSB 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 -46ama 11010010olan 210bu 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 chargenellikle 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 chardeğ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 chararalığı 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 charAritmetik kullanılırken kırmızı (255, 0, 0) ortalaması (85, 85, 85) olur . Ancak, değerler signed chars (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_tve uint8_ttürleridir.
int8_tve uint8_tisteğe bağlıdır ve bayt boyutunun tam olarak 8 bit olmadığı mimarilerde tanımlanmamıştır. Tersine, signed charve unsigned charher zaman kullanılabilir ve en az 8 bit tutma garantisi vardır. Ortak bir yol olabilir, ancak en güvenli yöntem olmayabilir .
signed charve 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 intve unsigned intbunun yerine bir nedenden dolayı?
signed charve unsigned charile 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.
charve unsigned chartü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 char0 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). charBir "karakter" olarak düşünüyor olabilirsiniz, ama bu gerçekten sayısal bir değerdir. Normal charimzalanmış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_MINve CHAR_MAXimzası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 charyalnı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 chardeğ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 charve 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++ptrmemcpy
unsigned chartüm bitlerin kalbidir. ALL platformu için neredeyse ALL derleyicisinde, an unsigned charsadece 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ı chartü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_tvb 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 signedveya unsignedkö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 charve unsigned charher 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 chardüşündüğümüz takdirde char letter = 'A', 'A' içinde 65 ikili temsil olduğu ASCII/Unicode65 saklanabilir ise, -65 da saklanabilir. ASCII/UnicodeNegatif 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