Dalam C / C ++, untuk apa sebuah unsigned char
digunakan? Apa bedanya dengan yang biasa char
?
Dalam C ++, ada tiga yang berbeda jenis karakter:
char
signed char
unsigned char
Jika Anda menggunakan jenis karakter untuk teks , gunakan yang tidak memenuhi syarat char
:
'a'
atau '0'
."abcde"
Itu juga berfungsi sebagai nilai angka, tetapi tidak ditentukan apakah nilai itu diperlakukan sebagai ditandatangani atau tidak ditandatangani. Waspadalah perbandingan karakter melalui ketidaksetaraan - meskipun jika Anda membatasi diri Anda pada ASCII (0-127) Anda hampir aman.
Jika Anda menggunakan tipe karakter sebagai angka , gunakan:
signed char
, yang memberi Anda setidaknya kisaran -127 hingga 127. (-128 hingga 127 adalah umum)unsigned char
, yang memberi Anda setidaknya rentang 0 hingga 255."Setidaknya", karena standar C ++ hanya memberikan kisaran nilai minimum yang harus dicakup oleh setiap tipe numerik. sizeof (char)
diperlukan 1 (yaitu satu byte), tetapi satu byte secara teori bisa jadi misalnya 32 bit. sizeof
masih akan melaporkan ukurannya sebagai1
- artinya Anda bisa memilikinya sizeof (char) == sizeof (long) == 1
.
sizeof
karena itu bukan fungsi tetapi operator. Ini bahkan gaya yang lebih baik untuk menghilangkan tanda kurung ketika mengambil ukuran variabel.sizeof *p
atausizeof (int)
. Ini membuatnya jelas dengan cepat jika itu berlaku untuk tipe atau variabel. Demikian juga, terlalu berlebihan untuk menempatkan tanda kurung setelahreturn
. Itu bukan fungsi.char
: ini adalah tipe karakter literal suka'a'
atau'0'
." benar dalam C ++ tetapi tidak C. Dalam C,'a'
adalahint
.Ini tergantung pada implementasi, karena standar C TIDAK mendefinisikan ke-ditandatangani-an dari
char
. Bergantung pada platform, char mungkinsigned
atauunsigned
, jadi Anda perlu secara eksplisit memintasigned char
atauunsigned char
apakah implementasi Anda bergantung padanya. Cukup gunakanchar
jika Anda bermaksud untuk mewakili karakter dari string, karena ini akan cocok dengan apa yang platform Anda masukkan ke dalam string.Perbedaan antara
signed char
danunsigned char
seperti yang Anda harapkan. Pada kebanyakan platform,signed char
akan menjadi bilangan pelengkap 8-bit dua mulai dari-128
ke127
, danunsigned char
akan menjadi integer 8-bit tanpa tanda (0
hingga255
). Perhatikan standar TIDAK mengharuskanchar
jenis memiliki 8 bit, hanya itusizeof(char)
kembali1
. Anda bisa mendapatkan di jumlah bit dalam char denganCHAR_BIT
dilimits.h
. Ada beberapa jika ada platform hari ini di mana ini akan menjadi sesuatu selain8
.Ada ringkasan yang bagus dari masalah ini di sini .
Seperti yang telah disebutkan orang lain sejak saya memposting ini, Anda lebih baik menggunakan
int8_t
danuint8_t
jika Anda benar-benar ingin mewakili bilangan bulat kecil.sumber
CHAR_BIT
diperlukan setidaknya 8 bit oleh standar.Karena saya merasa itu benar-benar diperlukan, saya hanya ingin menyatakan beberapa aturan C dan C ++ (mereka sama dalam hal ini). Pertama, semua bit dari
unsigned char
berpartisipasi dalam menentukan nilai jika benda unsigned char. Kedua,unsigned char
secara eksplisit dinyatakan tidak ditandatangani.Sekarang, saya berdiskusi dengan seseorang tentang apa yang terjadi ketika Anda mengonversi nilai
-1
tipe int keunsigned char
. Dia menolak gagasan bahwa hasilnyaunsigned char
memiliki semua bit diatur ke 1, karena dia khawatir tentang representasi tanda. Tetapi dia tidak harus melakukannya. Segera mengikuti aturan ini bahwa konversi melakukan apa yang dimaksudkan:Itu deskripsi matematis. C ++ menjelaskannya dalam hal modulo calculus, yang menghasilkan aturan yang sama. Bagaimanapun, apa yang tidak dijamin adalah bahwa semua bit dalam integer
-1
adalah satu sebelum konversi. Jadi, apa yang kita miliki sehingga kita dapat mengklaim bahwa hasilnyaunsigned char
memiliki semuaCHAR_BIT
bitnya berubah menjadi 1?UCHAR_MAX+1
ke-1
akan menghasilkan nilai dalam rentang, yaituUCHAR_MAX
Sudah cukup, sebenarnya! Jadi, kapan pun Anda ingin
unsigned char
memiliki semua bitnya, Anda memilikinyaIni juga mengikuti bahwa konversi tidak hanya memotong bit urutan yang lebih tinggi. Acara yang beruntung untuk komplemen dua adalah bahwa itu hanya pemotongan di sana, tetapi hal yang sama tidak selalu berlaku untuk representasi tanda lainnya.
sumber
UCHAR_MAX
?(unsigned type)-1
semacam idiom.~0
bukan.int x = 1234
danchar *y = &x
. Representasi biner dari1234
is00000000 00000000 00000100 11010010
. Mesin saya sedikit endian sehingga membalik dan menyimpannya dalam memori11010010 00000100 00000000 00000000
LSB yang lebih dulu. Sekarang Bagian Utama. jika saya gunakanprintf("%d" , *p)
.printf
akan membaca byte pertama11010010
hanya output-46
tetapi11010010
adalah210
jadi mengapa mencetak-46
. Saya benar-benar bingung, saya kira beberapa char to integer promotion melakukan sesuatu tetapi saya tidak tahu.Sebagai contoh, penggunaan char yang tidak ditandatangani :
unsigned char
sering digunakan dalam grafik komputer, yang sangat sering (meskipun tidak selalu) menetapkan satu byte untuk setiap komponen warna. Adalah umum untuk melihat warna RGB (atau RGBA) direpresentasikan sebagai 24 (atau 32) bit, masing-masingunsigned char
. Karenaunsigned char
nilai berada dalam kisaran [0,255], nilai biasanya ditafsirkan sebagai:Jadi Anda akan berakhir dengan RGB merah sebagai (255,0,0) -> (100% merah, 0% hijau, 0% biru).
Mengapa tidak menggunakan a
signed char
? Aritmatika dan pergeseran bit menjadi bermasalah. Seperti yang sudah dijelaskan,signed char
kisaran a pada dasarnya digeser oleh -128. Metode yang sangat sederhana dan naif (kebanyakan tidak digunakan) untuk mengkonversi RGB ke grayscale adalah dengan rata-rata ketiga komponen warna, tetapi ini mengalami masalah ketika nilai-nilai komponen warna negatif. Merah (255, 0, 0) rata-rata hingga (85, 85, 85) saat menggunakanunsigned char
aritmatika. Namun, jika nilainyasigned char
s (127, -128, -128), kita akan berakhir dengan (-99, -99, -99), yang akan menjadi (29, 29, 29) diunsigned char
ruang kita , yang tidak benar .sumber
Jika Anda ingin menggunakan karakter sebagai integer kecil, cara paling aman untuk melakukannya adalah dengan
int8_t
danuint8_t
tipe.sumber
int8_t
danuint8_t
bersifat opsional dan tidak didefinisikan pada arsitektur di mana ukuran byte tidak tepat 8 bit. Sebaliknya,signed char
danunsigned char
selalu tersedia dan dijamin untuk menampung setidaknya 8 bit. Ini mungkin cara yang umum tetapi bukan yang paling aman .signed char
danunsigned char
? Atau Anda akan merekomendasikan alternatif "aman" yang lebih baik dalam kasus tertentu? Misalnya untuk tetap dengan tipe integer "nyata"signed int
danunsigned int
bukannya karena alasan tertentu?signed char
danunsigned char
portabel untuk semua implementasi yang sesuai dan akan menghemat ruang penyimpanan tetapi dapat menyebabkan peningkatan ukuran kode. Dalam beberapa kasus, seseorang akan menghemat lebih banyak ruang penyimpanan dengan menyimpan nilai-nilai kecil dalam bitfields atau bit tunggal dari tipe integer biasa. Tidak ada jawaban mutlak untuk pertanyaan ini, ketepatan pendekatan ini tergantung pada kasus spesifik yang dihadapi. Dan jawaban ini toh tidak menjawab pertanyaan itu.unsigned char
hanya mengambil nilai positif .... seperti 0 hingga 255dimana sebagai
signed char
mengambil nilai positif dan negatif .... seperti -128 hingga +127sumber
char
danunsigned char
tidak dijamin menjadi tipe 8-bit di semua platform — mereka dijamin 8-bit atau lebih besar. Beberapa platform memiliki byte 9-bit, 32-bit, atau 64-bit . Namun, platform yang paling umum saat ini (Windows, Mac, Linux x86, dll.) Memiliki byte 8-bit.sumber
signed char
memiliki rentang -128 hingga 127;unsigned char
memiliki rentang 0 hingga 255.char
akan sama dengan char yang ditandatangani atau char yang tidak ditandatangani, tergantung pada kompiler, tetapi merupakan tipe yang berbeda.Jika Anda menggunakan string gaya-C, gunakan saja
char
. Jika Anda perlu menggunakan karakter untuk aritmatika (sangat jarang), tentukan ditandatangani atau tidak ditandatangani secara eksplisit untuk portabilitas.sumber
An
unsigned char
adalah nilai byte yang tidak ditandatangani (0 hingga 255). Anda mungkin berpikir untukchar
menjadi "karakter" tetapi itu benar-benar nilai numerik. Regulerchar
ditandatangani, sehingga Anda memiliki 128 nilai, dan nilai-nilai ini dipetakan ke karakter menggunakan pengkodean ASCII. Namun dalam kedua kasus tersebut, apa yang Anda simpan dalam memori adalah nilai byte.sumber
Dalam hal nilai langsung, char biasa digunakan ketika nilai diketahui berada di antara
CHAR_MIN
danCHAR_MAX
sementara char yang tidak ditandatangani menyediakan dua kali lipat rentang di ujung positif. Misalnya, jikaCHAR_BIT
8, kisaran regulerchar
hanya dijamin [0, 127] (karena dapat ditandatangani atau tidak ditandatangani) sementaraunsigned char
akan [0, 255] dansigned char
akan [-127, 127].Dalam hal apa yang digunakan untuk itu, standar memungkinkan objek POD (data lama polos) untuk secara langsung dikonversi ke array char unsigned. Ini memungkinkan Anda untuk memeriksa representasi dan pola bit objek. Jaminan yang sama untuk hukuman jenis aman tidak ada untuk char atau char yang ditandatangani.
sumber
unsigned char
, bukan array yang khusus, & setiap "konversi" hanya secara formal didefinisikan oleh menyalin dari objek untuk nyata, menyatakan array yang dariunsigned char
& kemudian memeriksa yang terakhir. Tidak jelas apakah OR dapat secara langsung ditafsirkan ulang sebagai array seperti itu, dengan kelonggaran untuk aritmatika pointer yang diperlukan, yaitu apakah "urutan"==
"array" dalam penggunaan ini. Ada Isu Inti # 1701 dibuka dengan harapan mendapatkan klarifikasi ini. Syukurlah, karena ambiguitas ini benar-benar mengganggu saya baru-baru ini.unsigned char
OR atau kemudian melanjutkan menggunakan++ptr
dari sana untuk membaca setiap byte itu ... tapi AFAICT, itu tidak secara khusus didefinisikan sebagai diizinkan, jadi kami dibiarkan untuk menyimpulkan bahwa itu 'mungkin OK' dari banyak bagian lain (dan dalam banyak hal, keberadaan belakamemcpy
) dalam Standar, mirip dengan teka-teki gambar. Yang tidak ideal. Yah, mungkin kata-katanya akan membaik pada akhirnya. Inilah masalah CWG yang saya sebutkan tetapi tidak memiliki ruang untuk menautkan - open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1701unsigned char
adalah jantung dari semua tipu daya bit. Di hampir SEMUA kompiler untuk platform SEMUAunsigned char
hanyalah sebuah byte dan integer unsigned dari (biasanya) 8 bit yang dapat diperlakukan sebagai integer kecil atau paket bit.Dalam kecanduan, seperti yang orang lain katakan, standar tidak mendefinisikan tanda char. sehingga Anda memiliki 3 berbeda
char
jenis:char
,signed char
,unsigned char
.sumber
Jika Anda suka menggunakan berbagai jenis panjang tertentu dan signedness, Anda mungkin lebih baik dengan
uint8_t
,int8_t
,uint16_t
, dll hanya karena mereka melakukan apa yang mereka katakan.sumber
Beberapa googling menemukan ini , di mana orang berdiskusi tentang ini.
Char unsigned pada dasarnya adalah satu byte. Jadi, Anda akan menggunakan ini jika Anda memerlukan satu byte data (misalnya, mungkin Anda ingin menggunakannya untuk mengaktifkan dan menonaktifkan flag untuk diteruskan ke suatu fungsi, seperti yang sering dilakukan di Windows API).
sumber
Char yang tidak ditandai menggunakan bit yang dicadangkan untuk tanda char biasa sebagai nomor lain. Ini mengubah rentang ke [0 - 255] sebagai kebalikan dari [-128 - 127].
Umumnya karakter unsigned digunakan ketika Anda tidak ingin tanda. Ini akan membuat perbedaan ketika melakukan hal-hal seperti menggeser bit (pergeseran memperluas tanda) dan hal-hal lain ketika berurusan dengan char sebagai byte daripada menggunakannya sebagai angka.
sumber
unsigned char
hanya mengambil nilai positif: 0 hingga 255 sementarasigned char
mengambil nilai positif dan negatif: -128 hingga +127.sumber
dikutip dari buku "the c programming laugage":
Kualifikasi
signed
atauunsigned
dapat diterapkan ke char atau bilangan bulat apa pun. bilangan unsigned selalu positif atau nol, dan mematuhi hukum modulith aritmetika 2 ^ n, di mana n adalah jumlah bit dalam tipe. Jadi, misalnya, jika karakter adalah 8 bit, variabel karakter yang tidak ditandai memiliki nilai antara 0 dan 255, sedangkan karakter yang ditandatangani memiliki nilai antara -128 dan 127 (dalam mesin komplemen dua.) Apakah karakter karakter yang ditandatangani atau tidak adalah mesin -dependen, tetapi karakter yang dapat dicetak selalu positif.sumber
signed char
danunsigned char
keduanya mewakili 1byte, tetapi mereka memiliki rentang yang berbeda.Dalam
signed char
jika kita mempertimbangkanchar letter = 'A'
, 'A' adalah mewakili biner dari 65 diASCII/Unicode
, Jika 65 dapat disimpan, -65 juga dapat disimpan. Tidak ada nilai biner negatif diASCII/Unicode
sana karena tidak perlu khawatir tentang nilai negatif.Contoh
Output -:
sumber