Dalam C / C ++, untuk apa sebuah unsigned char
digunakan? Apa bedanya dengan yang biasa char
?
Dalam C / C ++, untuk apa sebuah unsigned char
digunakan? Apa bedanya dengan yang biasa char
?
Jawaban:
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
atau 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 signed
atau unsigned
, jadi Anda perlu secara eksplisit meminta signed char
atau unsigned char
apakah implementasi Anda bergantung padanya. Cukup gunakan char
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
dan unsigned char
seperti yang Anda harapkan. Pada kebanyakan platform, signed char
akan menjadi bilangan pelengkap 8-bit dua mulai dari -128
ke 127
, dan unsigned char
akan menjadi integer 8-bit tanpa tanda ( 0
hingga 255
). Perhatikan standar TIDAK mengharuskan char
jenis memiliki 8 bit, hanya itu sizeof(char)
kembali 1
. Anda bisa mendapatkan di jumlah bit dalam char dengan CHAR_BIT
di 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_t
dan uint8_t
jika Anda benar-benar ingin mewakili bilangan bulat kecil.
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 ke unsigned char
. Dia menolak gagasan bahwa hasilnya unsigned 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:
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.3p2
dalam 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 -1
adalah satu sebelum konversi. Jadi, apa yang kita miliki sehingga kita dapat mengklaim bahwa hasilnya unsigned char
memiliki semua CHAR_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 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)-1
semacam idiom. ~0
bukan.
int x = 1234
dan 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 00000000
LSB yang lebih dulu. Sekarang Bagian Utama. jika saya gunakan printf("%d" , *p)
. printf
akan membaca byte pertama 11010010
hanya output -46
tetapi 11010010
adalah 210
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-masing unsigned char
. Karena unsigned 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 menggunakan unsigned char
aritmatika. Namun, jika nilainya signed char
s (127, -128, -128), kita akan berakhir dengan (-99, -99, -99), yang akan menjadi (29, 29, 29) di unsigned char
ruang kita , yang tidak benar .
Jika Anda ingin menggunakan karakter sebagai integer kecil, cara paling aman untuk melakukannya adalah dengan int8_t
dan uint8_t
tipe.
int8_t
dan uint8_t
bersifat opsional dan tidak didefinisikan pada arsitektur di mana ukuran byte tidak tepat 8 bit. Sebaliknya, signed char
dan unsigned char
selalu tersedia dan dijamin untuk menampung setidaknya 8 bit. Ini mungkin cara yang umum tetapi bukan yang paling aman .
signed char
dan unsigned char
? Atau Anda akan merekomendasikan alternatif "aman" yang lebih baik dalam kasus tertentu? Misalnya untuk tetap dengan tipe integer "nyata" signed int
dan unsigned 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.
char
dan unsigned 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.
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.
An unsigned char
adalah nilai byte yang tidak ditandatangani (0 hingga 255). Anda mungkin berpikir untuk char
menjadi "karakter" tetapi itu benar-benar nilai numerik. Reguler char
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.
Dalam hal nilai langsung, char biasa digunakan ketika nilai diketahui berada di antara CHAR_MIN
dan CHAR_MAX
sementara char yang tidak ditandatangani menyediakan dua kali lipat rentang di ujung positif. Misalnya, jika CHAR_BIT
8, kisaran reguler char
hanya dijamin [0, 127] (karena dapat ditandatangani atau tidak ditandatangani) sementara unsigned char
akan [0, 255] dan signed 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.
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 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 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 char
adalah jantung dari semua tipu daya bit. Di hampir SEMUA kompiler untuk platform SEMUA unsigned 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
.
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 signed
atau unsigned
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.
signed char
dan unsigned char
keduanya mewakili 1byte, tetapi mereka memiliki rentang yang berbeda.
Type | range
-------------------------------
signed char | -128 to +127
unsigned char | 0 to 255
Dalam signed char
jika 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