Dalam C / C ++, untuk apa sebuah unsigned chardigunakan? Apa bedanya dengan yang biasa char?
Dalam C / C ++, untuk apa sebuah unsigned chardigunakan? Apa bedanya dengan yang biasa char?
Jawaban:
Dalam C ++, ada tiga yang berbeda jenis karakter:
charsigned charunsigned charJika 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. sizeofmasih akan melaporkan ukurannya sebagai1 - artinya Anda bisa memilikinya sizeof (char) == sizeof (long) == 1.
sizeofkarena itu bukan fungsi tetapi operator. Ini bahkan gaya yang lebih baik untuk menghilangkan tanda kurung ketika mengambil ukuran variabel. sizeof *patau sizeof (int). Ini membuatnya jelas dengan cepat jika itu berlaku untuk tipe atau variabel. Demikian juga, terlalu berlebihan untuk menempatkan tanda kurung setelah return. Itu bukan fungsi.
char: ini adalah tipe karakter literal suka 'a'atau '0'." benar dalam C ++ tetapi tidak C. Dalam C, 'a'adalah int.
Ini tergantung pada implementasi, karena standar C TIDAK mendefinisikan ke-ditandatangani-an dari char. Bergantung pada platform, char mungkin signedatau unsigned, jadi Anda perlu secara eksplisit meminta signed charatau unsigned charapakah implementasi Anda bergantung padanya. Cukup gunakan charjika Anda bermaksud untuk mewakili karakter dari string, karena ini akan cocok dengan apa yang platform Anda masukkan ke dalam string.
Perbedaan antara signed chardan unsigned charseperti yang Anda harapkan. Pada kebanyakan platform, signed charakan menjadi bilangan pelengkap 8-bit dua mulai dari -128ke 127, dan unsigned charakan menjadi integer 8-bit tanpa tanda ( 0hingga 255). Perhatikan standar TIDAK mengharuskan charjenis memiliki 8 bit, hanya itu sizeof(char)kembali 1. Anda bisa mendapatkan di jumlah bit dalam char dengan CHAR_BITdi limits.h. Ada beberapa jika ada platform hari ini di mana ini akan menjadi sesuatu selain 8.
Ada ringkasan yang bagus dari masalah ini di sini .
Seperti yang telah disebutkan orang lain sejak saya memposting ini, Anda lebih baik menggunakan int8_tdan uint8_tjika Anda benar-benar ingin mewakili bilangan bulat kecil.
CHAR_BITdiperlukan 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 charberpartisipasi dalam menentukan nilai jika benda unsigned char. Kedua, unsigned charsecara eksplisit dinyatakan tidak ditandatangani.
Sekarang, saya berdiskusi dengan seseorang tentang apa yang terjadi ketika Anda mengonversi nilai -1tipe int ke unsigned char. Dia menolak gagasan bahwa hasilnya unsigned charmemiliki 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:
Jika tipe baru tidak ditandatangani, nilainya dikonversi dengan berulang kali menambahkan atau mengurangi satu lebih dari nilai maksimum yang dapat direpresentasikan dalam tipe baru hingga nilainya berada dalam kisaran tipe baru. (
6.3.1.3p2dalam konsep C99)
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 -1adalah satu sebelum konversi. Jadi, apa yang kita miliki sehingga kita dapat mengklaim bahwa hasilnya unsigned charmemiliki semua CHAR_BITbitnya berubah menjadi 1?
UCHAR_MAX+1ke -1akan menghasilkan nilai dalam rentang, yaituUCHAR_MAXSudah cukup, sebenarnya! Jadi, kapan pun Anda ingin unsigned charmemiliki semua bitnya, Anda memilikinya
unsigned char c = (unsigned char)-1;
Ini 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.
UCHAR_MAX?
(unsigned type)-1semacam idiom. ~0bukan.
int x = 1234dan char *y = &x. Representasi biner dari 1234 is 00000000 00000000 00000100 11010010. Mesin saya sedikit endian sehingga membalik dan menyimpannya dalam memori 11010010 00000100 00000000 00000000LSB yang lebih dulu. Sekarang Bagian Utama. jika saya gunakan printf("%d" , *p). printfakan membaca byte pertama 11010010hanya output -46tetapi 11010010adalah 210jadi 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 charsering 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-masing unsigned char. Karena unsigned charnilai 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 charkisaran 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 menggunakan unsigned chararitmatika. Namun, jika nilainya signed chars (127, -128, -128), kita akan berakhir dengan (-99, -99, -99), yang akan menjadi (29, 29, 29) di unsigned charruang kita , yang tidak benar .
Jika Anda ingin menggunakan karakter sebagai integer kecil, cara paling aman untuk melakukannya adalah dengan int8_tdan uint8_ttipe.
int8_tdan uint8_tbersifat opsional dan tidak didefinisikan pada arsitektur di mana ukuran byte tidak tepat 8 bit. Sebaliknya, signed chardan unsigned charselalu tersedia dan dijamin untuk menampung setidaknya 8 bit. Ini mungkin cara yang umum tetapi bukan yang paling aman .
signed chardan unsigned char? Atau Anda akan merekomendasikan alternatif "aman" yang lebih baik dalam kasus tertentu? Misalnya untuk tetap dengan tipe integer "nyata" signed intdan unsigned intbukannya karena alasan tertentu?
signed chardanunsigned 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.
chardan unsigned chartidak 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.
signed charmemiliki rentang -128 hingga 127; unsigned charmemiliki 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.
An unsigned charadalah nilai byte yang tidak ditandatangani (0 hingga 255). Anda mungkin berpikir untuk charmenjadi "karakter" tetapi itu benar-benar nilai numerik. Reguler charditandatangani, 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.
Dalam hal nilai langsung, char biasa digunakan ketika nilai diketahui berada di antara CHAR_MINdan CHAR_MAXsementara char yang tidak ditandatangani menyediakan dua kali lipat rentang di ujung positif. Misalnya, jika CHAR_BIT8, kisaran reguler charhanya dijamin [0, 127] (karena dapat ditandatangani atau tidak ditandatangani) sementara unsigned charakan [0, 255] dan signed charakan [-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.
unsigned char, bukan array yang khusus, & setiap "konversi" hanya secara formal didefinisikan oleh menyalin dari objek untuk nyata, menyatakan array yang dari unsigned 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 charOR atau kemudian melanjutkan menggunakan ++ptrdari 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 belaka memcpy) 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#1701
unsigned charadalah jantung dari semua tipu daya bit. Di hampir SEMUA kompiler untuk platform SEMUA unsigned charhanyalah 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 charjenis: char, signed char, unsigned char.
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.
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).
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.
dikutip dari buku "the c programming laugage":
Kualifikasi signedatau unsigneddapat 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.
signed chardan unsigned charkeduanya mewakili 1byte, tetapi mereka memiliki rentang yang berbeda.
Type | range
-------------------------------
signed char | -128 to +127
unsigned char | 0 to 255
Dalam signed charjika kita mempertimbangkan char 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
#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;
}
Output -:
Signed char(255) : -1
Unsigned char(255) : 255
Signed char(-128) : -128
Unsigned char(-128) : 128