it-swarm-id.com

Apa itu char yang tidak ditandatangani?

Dalam C/C++, untuk apa unsigned char digunakan? Apa bedanya dengan char biasa?

433
Landon Kuhn

Di C++, ada tiga tipe karakter berbeda :

  • char
  • signed char
  • unsigned char

Jika Anda menggunakan tipe karakter untuk teks , gunakan char yang tidak memenuhi syarat:

  • itu adalah jenis literal karakter seperti 'a' atau '0'.
  • itu adalah tipe yang membentuk string C seperti "abcde"

Ini juga berfungsi sebagai nilai angka, tetapi tidak ditentukan apakah nilai tersebut diperlakukan sebagai ditandatangani atau tidak. Waspadalah perbandingan karakter melalui ketidaksetaraan - meskipun jika Anda membatasi diri Anda untuk ASCII (0-127) Anda hampir aman.

Jika Anda menggunakan tipe karakter sebagai angka , gunakan:

  • signed char, yang memberi Anda setidaknya rentang -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) harus sebesar 1 (mis. satu byte), tetapi secara teori byte bisa berupa 32 bit. sizeof MASIH AKAN MELAPORKAN UKURANNYA SEBAGAI 1 - artinya Anda dapat memiliki sizeof (char) == sizeof (long) == 1.

513
Fruny

Ini tergantung pada implementasi, karena standar C TIDAK mendefinisikan keabsahan char. Bergantung pada platform, char mungkin signed atau unsigned, jadi Anda perlu secara eksplisit meminta signed char atau unsigned char jika implementasi Anda bergantung padanya. Cukup gunakan char jika Anda berniat 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 adalah seperti yang Anda harapkan. Pada kebanyakan platform, signed char akan menjadi nomor komplemen dua bit 8-bit mulai dari -128 hingga 127, dan unsigned char akan menjadi integer 8-bit unsigned (0 hingga 255). Perhatikan standar TIDAK mengharuskan jenis char memiliki 8 bit, hanya saja sizeof(char) mengembalikan 1. Anda bisa mendapatkan jumlah bit dalam char dengan CHAR_BIT di limits.h. Ada beberapa jika ada platform hari ini di mana ini akan menjadi sesuatu yang lain selain 8.

Ada ringkasan yang bagus tentang 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 integer kecil.

81
Todd Gamblin

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 ada objek char yang tidak ditandatangani. Kedua, unsigned char secara eksplisit dinyatakan tidak ditandatangani.

Sekarang, saya berdiskusi dengan seseorang tentang apa yang terjadi ketika Anda mengonversi nilai -1 dari tipe int ke unsigned char. Dia menolak gagasan bahwa unsigned char yang dihasilkan memiliki semua bitnya 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 menambah 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 unsigned char yang dihasilkan memiliki semua CHAR_BIT bitnya berubah menjadi 1?

  1. Semua bit berpartisipasi dalam menentukan nilainya - yaitu, tidak ada bit padding yang terjadi pada objek.
  2. Menambahkan hanya satu kali UCHAR_MAX+1 ke -1 akan menghasilkan nilai dalam rentang, yaitu UCHAR_MAX

Cukup, sebenarnya! Jadi, setiap kali Anda ingin memiliki unsigned char memiliki semua bitnya, Anda lakukan

unsigned char c = (unsigned char)-1;

Itu juga mengikuti bahwa konversi adalah tidak hanya memotong bit urutan yang lebih tinggi. Acara yang beruntung untuk komplemen dua adalah hanya pemotongan di sana, tetapi hal yang sama tidak selalu benar untuk representasi tanda lainnya.

35

Sebagai contoh, penggunaan nsigned char:

nsigned 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 sebuah char tidak ditandai. Karena nsigned char nilai termasuk dalam rentang [0,255], nilai biasanya ditafsirkan sebagai:

  • 0 artinya tidak ada komponen warna yang diberikan.
  • 255 artinya 100% dari pigmen warna yang diberikan.

Jadi Anda akan berakhir dengan RGB merah sebagai (255,0,0) -> (100% merah, 0% hijau, 0% biru).

Mengapa tidak menggunakan char yang ditandatangani? Aritmatika dan pergeseran bit menjadi bermasalah. Seperti yang sudah dijelaskan, rentang char terdaftar 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 ke (85, 85, 85) saat menggunakan nsigned char aritmatika. Namun, jika nilainya menandatangani char s (127, -128, -128), kita akan berakhir dengan (-99, -99, -99), yang akan menjadi (29, 29, 29) di ruang nsigned char kami, yang tidak benar.

24
Zachary Garrett

Jika Anda ingin menggunakan karakter sebagai integer kecil, cara teraman untuk melakukannya adalah dengan tipe int8_tand uint8_t.

12
jbleners

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 kompilernya, tetapi merupakan tipe yang berbeda.

Jika Anda menggunakan string gaya-C, cukup gunakan char. Jika Anda perlu menggunakan karakter untuk aritmatika (sangat jarang), tentukan ditandatangani atau tidak ditandatangani secara eksplisit untuk portabilitas.

5
James Hopkin

char dan unsigned char tidak dijamin menjadi tipe 8-bit pada semua platform — platform dijamin 8-bit atau lebih besar. Beberapa platform memiliki 9-bit, 32-bit, atau 64-bit byte . Namun, platform paling umum saat ini (Windows, Mac, Linux x86, dll.) Memiliki byte 8-bit.

5
bk1e

Dalam hal nilai langsung, char biasa digunakan ketika nilainya diketahui antara CHAR_MIN dan CHAR_MAX sementara char yang tidak ditandatangani menyediakan dua kali lipat rentang di ujung positif. Misalnya, jika CHAR_BIT adalah 8, kisaran char reguler hanya dijamin [0, 127] (karena dapat ditandatangani atau tidak ditandatangani) sedangkan unsigned char akan menjadi [0, 255] dan signed char akan menjadi [-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.

4
Julienne Walker

unsigned char hanya mengambil nilai positif .... seperti ke 255

dimana sebagai

signed char mengambil nilai positif dan negatif .... seperti - 128 ke + 127

4
munna

Karakter unsigned adalah nilai byte (unsigned) (0 hingga 255). Anda mungkin berpikir tentang "char" dalam hal menjadi "karakter" tetapi itu benar-benar nilai numerik. "Char" reguler ditandatangani, jadi Anda memiliki 128 nilai, dan nilai-nilai ini dipetakan ke karakter menggunakan pengodean ASCII. Namun dalam kedua kasus tersebut, apa yang Anda simpan dalam memori adalah nilai byte.

3
Zac Gochenour

Jika Anda suka menggunakan berbagai jenis panjang dan penandatanganan khusus, Anda mungkin lebih baik dengan uint8_t, int8_t, uint16_t, dll hanya karena mereka melakukan persis apa yang mereka katakan.

2
Dark Shikari

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 berhadapan dengan char sebagai byte daripada menggunakannya sebagai angka.

2
JasonOfEarth

unsigned char adalah jantung dari semua tipu daya bit. Di hampir semua kompiler SEMUA untuk platform SEMUA, char unsigned hanyalah BYTE. 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. jadi Anda memiliki 3 tipe "char" yang berbeda: char, char yang ditandatangani, char yang tidak ditandatangani.

2
ugasoft

Beberapa googling ditemukan 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).

1
dbrien

unsigned char hanya mengambil nilai positif: 0 hingga 255 char yang ditandatangani mengambil nilai positif dan negatif: -128 hingga +127

0
NL628

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 modulithith 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.

0
ZhaoGang