Apa itu CHAR_BIT?

93

Mengutip kode untuk menghitung nilai absolut integer (abs) tanpa bercabang dari http://graphics.stanford.edu/~seander/bithacks.html :

int v;           // we want to find the absolute value of v
unsigned int r;  // the result goes here 
int const mask = v >> sizeof(int) * CHAR_BIT - 1;

r = (v + mask) ^ mask;

Variasi yang dipatenkan:

r = (v ^ mask) - mask;

Apa CHAR_BITdan bagaimana menggunakannya?

dato datuashvili
sumber

Jawaban:

0

Anda harus menyadari bahwa kode ini bergantung pada perilaku bitshift yang ditentukan oleh implementasi pada jenis yang ditandatangani. gcc berjanji untuk selalu memberikan perilaku yang waras (sign-bit-extension) tetapi ISO C memungkinkan implementasi untuk mengisi bit-bit atas dengan nol.

Salah satu cara mengatasi masalah ini:

#ifdef HAVE_SIGN_EXTENDING_BITSHIFT
int const mask = v >> sizeof(int) * CHAR_BIT - 1;
#else
int const mask = -((unsigned)v >> sizeof(int) * CHAR_BIT - 1);
#endif

Anda Makefileatau config.hdll. Dapat HAVE_SIGN_EXTENDING_BITSHIFTditentukan pada waktu pembuatan tergantung pada platform Anda.

R .. GitHub BERHENTI ICE BANTUAN
sumber
122
Saya tidak mengerti bagaimana ini bisa menjadi jawaban yang diterima karena tidak menjawab pertanyaan, meskipun itu adalah komentar yang sangat menarik.
qdii
16
@ Mauris: Seseorang mengedit pertanyaan dan mempromosikan sub-pertanyaan ke judul pertanyaan. Judul aslinya memang mengerikan, tetapi pertanyaan OP adalah tentang bagaimana kode hack bit yang dikutip bekerja, dan "tidak, setidaknya tidak portabel, dan inilah alasannya" adalah jawaban yang berguna.
R .. GitHub STOP HELPING ICE
12
Oh saya mengerti. Sayangnya, pertanyaan ini muncul sangat tinggi di hasil Google Penelusuran untuk "Apa itu CHAR_BIT?" , meskipun itu bukan pertanyaan aslinya. :( Dengan penjelasan Anda, saya mengerti mengapa Anda menulis jawaban ini, tetapi untuk anak cucu mungkin lebih berguna untuk (a) menghapus jawaban Anda dan menulis ulang sebagai komentar untuk pertanyaan, sehingga @ AraK muncul di atas, atau (b) edit jawaban Anda sehingga menjawab judul pertanyaan saat ini.
Lynn
1
Karena perbedaan maksud antara pertanyaan awal OP dan interpretasi editornya, tampaknya sifat dari permintaan asli telah berubah tanpa sengaja. Meskipun kedua pertanyaan (asli dan diedit) memiliki manfaat, perbedaan ini perlu diatasi. Sekarang saya bertanya: Bisakah jawaban ini ditambahkan ke wiki? Ini mungkin akan membantu orang-orang yang mencari jenis info ini, meskipun tidak berhubungan dengan pertanyaan awal. Setelah itu, pertanyaannya dapat diedit lagi, agar sesuai dengan permintaan asli dato datuashvili. Hanya pembaca yang peduli ...
2
Saya baru saja melihat sejarah pertanyaan ini dan pertanyaan asli sebenarnya tidak menanyakan di mana pun bagaimana kode bekerja. Pertanyaan yang dipromosikan editor menjadi judul adalah satu-satunya pertanyaan aktual di sana.
plugwash
230

CHAR_BITadalah jumlah bit char. Saat ini, hampir semua arsitektur menggunakan 8 bit per byte, tetapi tidak selalu demikian. Beberapa mesin lama dulunya memiliki byte 7-bit.

Itu dapat ditemukan di <limits.h>.

AraK
sumber
3
Beberapa DSP memiliki 10 bit-byte atau lebih.
Juri Robl
64
C membutuhkan CHAR_BIT>=8dan memungkinkan nilai yang jauh lebih besar untuk DSP yang hanya memiliki satu ukuran tipe, seringkali 32bit. POSIX membutuhkan CHAR_BIT==8. Secara umum, Anda dapat mengasumsikan arsitektur multi-pengguna / multitasking berorientasi server atau berorientasi penggunaan interaktif dengan kemungkinan terhubung ke internet atau bertukar data tekstual dengan dunia luar CHAR_BIT==8.
R .. GitHub STOP HELPING ICE
6
@caf: Tidak, C99 membutuhkan tipe int8_tdan uint8_tada. Dengan demikian terdapat jenis lebar 8. Sejak sizeofjenis harus kompatibel dengan sizeof charbenar-benar sizeof int8_tharus 1. Jadi CHAR_BIT == 8. Saya telah menulis sesuatu tentang obesitas itu di sini: gustedt.wordpress.com/2010/06/01/how-many-bits-has-a-byte
Jens Gustedt
22
@ Jens Gustedt: Harap kutip bagian dalam spesifikasi C99. Dari jenis bilangan bulat dengan lebar tepat, spesifikasi C99 menyatakan "Jenis ini opsional". (7.18.1.1/3) Namun, jenis lebar minimum dan lebar tercepat diperlukan.
jamesdlin
3
@jamesdlin & caf: maaf saya campur aduk. ya persyaratan yang saya maksud sebenarnya berasal dari POSIX for stdint.h. Jadi itu diperlukan, dan itu juga ditandai sebagai Ekstensi untuk standar ISO C , tanpa mengacu pada versi tertentu dari standar itu. Salahku.
Jens Gustedt
2

Mencoba menjawab pertanyaan eksplisit (apa itu CHAR_BIT) dan pertanyaan implisit (bagaimana cara kerjanya) di pertanyaan asli.


Sebuah karakter dalam C dan C ++ mewakili unit memori terkecil yang dapat ditangani oleh program C *

CHAR_BIT di C dan C ++ mewakili jumlah bit dalam karakter. Harus selalu minimal 8 karena persyaratan lain pada tipe karakter. Dalam prakteknya pada semua komputer tujuan umum modern tepat 8 tetapi beberapa sistem historis atau spesialis mungkin memiliki nilai yang lebih tinggi.

Java tidak memiliki kesetaraan CHAR_BIT atau sizeof, tidak perlu karena semua tipe primitif di Java memiliki ukuran tetap dan struktur internal objek tidak jelas bagi pemrogram. Jika menerjemahkan kode ini ke Java, Anda cukup mengganti "sizeof (int) * CHAR_BIT - 1" dengan nilai tetap 31.

Dalam kode khusus ini digunakan untuk menghitung jumlah bit dalam sebuah int. Ketahuilah bahwa perhitungan ini mengasumsikan bahwa tipe int tidak berisi bit padding apa pun.

Asumsikan bahwa compiler Anda memilih untuk memperpanjang pada pergeseran bit dari bilangan bertanda tangan dan mengasumsikan sistem Anda menggunakan representasi komplemen 2s untuk angka negatif, ini berarti bahwa "MASK" akan menjadi 0 untuk nilai positif atau nol dan -1 untuk nilai negatif.

Untuk meniadakan bilangan komplemen dua, kita perlu melakukan bitwise not dan kemudian menambahkan satu. Secara seimbang kita dapat mengurangi satu dan kemudian meniadakannya dengan bitwise.

Sekali lagi dengan asumsi representasi pelengkap dua -1 diwakili oleh semua orang, jadi eksklusif atau dengan -1 setara dengan negasi bitwise.

Jadi ketika v adalah nol jumlahnya dibiarkan sendiri, ketika v adalah satu dinegasikan.

Sesuatu yang harus diperhatikan adalah bahwa luapan bertanda di C dan C ++ merupakan perilaku yang tidak ditentukan. Jadi menggunakan implementasi ABS ini pada nilai paling negatif menyebabkan perilaku tidak terdefinisi. Ini dapat diperbaiki dengan menambahkan cast sedemikian rupa sehingga baris terakhir program dievaluasi dalam unsigned int.

* Yang biasanya sama dengan unit memori terkecil yang dapat ditangani oleh perangkat keras. Implementasi berpotensi menggabungkan beberapa unit memori yang dapat dialamatkan perangkat keras ke dalam satu unit memori yang dapat dialamatkan program atau membagi satu unit memori yang dapat dialamatkan perangkat keras menjadi beberapa unit memori yang dapat ditambahkan program.

plugwash
sumber