CHAR_BITとは何ですか?


91

http://graphics.stanford.edu/~seander/bithacks.htmlから分岐せずに整数絶対値(abs)を計算するコードを引用します

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;

特許取得済みのバリエーション:

r = (v ^ mask) - mask;

それは何でCHAR_BIT、どのように使用しますか?

回答:


-1

このコードは、署名された型に対する右ビットシフトの実装定義の動作に依存することに注意してください。gccは常に正常な動作(符号ビット拡張)を提供することを約束しますが、ISO Cでは、実装で上位ビットをゼロで埋めることができます。

この問題を回避する1つの方法:

#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

あなたのMakefileconfig.hなどを定義することができHAVE_SIGN_EXTENDING_BITSHIFT、ご使用のプラットフォームに応じて、ビルド時に。


120
非常に興味深いコメントですが、質問に回答しないため、これがどのように受け入れられる回答になるのかわかりません。
qdii 2013年

15
@Mauris:誰かが質問を編集して、質問のタイトルにサブ質問を追加しました。元のタイトルは確かにひどいものでしたが、OPの質問は、引用されたビットハックコードがどのように機能するかに関するものでした。
R .. GitHub ICEのヘルプ停止2016年

12
ああ、わかりました。悲しいことに、この質問は、「What is CHAR_BIT?」の Google検索結果に非常に多く表示されます。、それが元の質問ではなかったとしても。:(あなたの説明があれば、あなたがこの回答を書いた理由は理解できますが、後世には(a)回答を削除し、質問へのコメントとして書き直すと、@ AraKが上部に表示されるか、または(b)質問の現在のタイトルに回答するように回答を編集します
Lynn

1
OPの元の質問と編集者のその解釈の意図の違いにより、元の要求の性質が意図せず変更されたように見えます。両方の質問(オリジナルと編集済み)にはメリットがありますが、この矛盾に対処する必要があります。私は今尋ねます:この回答をウィキに追加できますか?これは、元の質問には関係ありませんが、このタイプの情報を検索している人々を助ける可能性があります。その後、dato datuashviliの元の要求に合わせて、質問を再度編集できます。ただ心配な読者...

2
私はこの質問の履歴を見ただけで、元の質問は実際にはコードがどのように機能するかを尋ねるものではありません。編集者がタイトルに昇格した質問は、そこにある唯一の実際の質問です。
プラグウォッシュ

224

CHAR_BITはのビット数ですchar。最近では、ほとんどすべてのアーキテクチャで1バイトあたり8ビットが使用されていますが、常にそうであるとは限りません。一部の古いマシンは、7ビットバイトを使用していました。

にあります<limits.h>


3
一部のDSPには10以上のビットバイトがあります。
Juri Robl、2010

64
CはCHAR_BIT>=8、単一のタイプサイズ(多くの場合32ビット)しかないDSPにはるかに大きな値を必要とし、許可します。POSIXにはが必要CHAR_BIT==8です。一般に、インターネットに接続したり、外部の世界とテキストデータを交換したりする可能性のあるマルチユーザー/マルチタスクサーバー指向またはインタラクティブ使用指向のアーキテクチャを想定できますCHAR_BIT==8
R .. GitHub ICE HELPING ICEの停止

6
@caf:いいえ、それはC99が型int8_tを必要とuint8_tし、存在することです。したがって、幅8のタイプが存在します。sizeofすべてのタイプと互換性sizeof charsizeof int8_tなければならないため、実際には1でなければなりませんCHAR_BIT == 8。私はその観察の周りにここに何かを書きました:gustedt.wordpress.com/2010/06/01/how-many-bits-has-a-byte
Jens Gustedt

22
@Jens Gustedt:C99仕様のセクションを引用してください。正確な幅の整数型のうち、C99仕様では「これらの型はオプションです」と記載されています。(7.18.1.1/3)ただし、最小幅タイプと最速幅タイプが必要です。
jamesdlin

3
@jamesdlin&caf:ごめんなさい。はい、私が言及した要件は、実際にはPOSIX forから来ていstdint.hます。したがって、それは必須であり、その規格の特定のバージョンを参照せずに、ISO C規格の拡張としてマークされています。私の悪い。
Jens Gustedt、2010

2

元の質問の明示的な質問(CHAR_BITとは)と暗黙の質問(これはどのように機能するか)の両方に回答しようとします。


CおよびC ++の文字は、Cプログラムがアドレス指定できるメモリの最小単位を表します*

CおよびC ++のCHAR_BITは、charのビット数を表します。char型に関する他の要件のため、常に少なくとも8でなければなりません。実際には、すべての現代の汎用コンピューターでは正確に8ですが、一部の歴史的または専門的なシステムはより高い値を持つ場合があります。

JavaにはCHAR_BITやsizeofに相当するものはありません。Javaのすべてのプリミティブ型はサイズが固定されており、オブジェクトの内部構造はプログラマにとって不透明なので、Javaには必要ありません。このコードをJavaに変換する場合は、「sizeof(int)* CHAR_BIT-1」を固定値31に置き換えるだけです。

この特定のコードでは、intのビット数を計算するために使用されています。この計算では、int型にパディングビットが含まれていないことを前提としています。

コンパイラが符号付き数値のビットシフトで符号拡張することを選択し、システムが負の数値に2の補数表現を使用すると仮定すると、「MASK」は正またはゼロの値の場合は0、負の値の場合は-1になります。

2の補数を否定するには、ビット単位の否定を実行してから1を追加する必要があります。同等に、1を減算してから、ビットごとに否定できます。

ここでも、2の補数表現-1はすべて1で表されると想定しているため、排他的または-1付きはビット単位の否定と同等です。

したがって、vが0の場合、数値はそのままになり、vが1の場合、無効になります。

注意すべきことは、CおよびC ++の符号付きオーバーフローは未定義の動作であることです。したがって、最も負の値でこのABS実装を使用すると、未定義の動作が発生します。これは、プログラムの最終行がunsigned intで評価されるようにキャストを追加することで修正できます。

*これは、ハードウェアがアドレス指定できるメモリの最小単位と同じですが、必ずしも必要ではありません。実装は、ハードウェアアドレス可能なメモリの複数のユニットを1つのプログラムアドレス可能なメモリに組み合わせるか、1つのユニットのハードウェアアドレス可能なメモリをプログラム可能なメモリの複数のユニットに分割することができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.