回答:
C ++には、3つの異なる文字タイプがあります。
char
signed char
unsigned char
テキストに文字タイプを使用している場合は、修飾なしを使用しますchar
。
'a'
orのような文字リテラルのタイプです'0'
。"abcde"
数値としても機能しますが、その値が符号付きとして扱われるか、符号なしとして扱われるかは不定です。不等式による文字比較に注意してください。ただし、ASCII(0〜127)に限定すると、安全です。
数値として文字タイプを使用している場合は、次を使用します。
signed char
、少なくとも -127から127の範囲を提供します。(-128から127が一般的)unsigned char
、これにより、少なくとも 0〜255の範囲が得られます。「少なくとも」。これは、C ++標準では、各数値型がカバーする必要のある値の最小範囲のみを提供するためです。sizeof (char)
1(つまり1バイト)である必要がありますが、1バイトは理論的にはたとえば32ビットにすることができます。sizeof
それでもとしてそのサイズを報告されるだろう1
あなたがいることを意味- 可能性が持っていますsizeof (char) == sizeof (long) == 1
。
sizeof
関数ではなく演算子なので、後にスペースを置くのが一般的です。変数のサイズをとるときに括弧を省略すると、さらに良いスタイルになります。sizeof *p
またはsizeof (int)
。これは、それが型または変数に適用される場合、すぐに明確になります。同様に、の後に括弧を置くことも冗長return
です。関数ではありません。
char
:'a'
またはのような文字リテラルのタイプです'0'
。」C ++ではtrueですが、Cで'a'
はありません。Cでは、ですint
。
C標準ではの符号付きが定義されていないため、これは実装に依存しますchar
。プラットフォームによっては、charがsigned
またはのunsigned
場合があるため、明示的に要求するsigned char
かunsigned char
、実装がそれに依存しているかどうかを確認する必要があります。char
これは、プラットフォームが文字列に入力するものと一致するため、文字列の文字を表す場合にのみ使用します。
違いsigned char
とは、unsigned char
あなたが期待通りです。ほとんどのプラットフォームでは、signed char
範囲の8ビットの2の補数になり-128
まで127
、およびunsigned char
8ビットの符号なし整数(あろう0
に255
)。標準では、char
型が8ビットである必要はなく、それだけがsizeof(char)
返されることに注意してください1
。あなたはと文字のビット数で取得することができますCHAR_BIT
でlimits.h
。ただし、これが以外のプラットフォームになる今日のプラットフォームはほとんどありませ8
ん。
この問題の良い要約がここにあります。
私がこれを投稿して以来他の人が述べたように、あなたは使用int8_t
したほうがよく、uint8_t
本当に小さな整数を表現したいのなら。
CHAR_BIT
規格では少なくとも8ビットである必要があります。
私はそれが本当に求められていると感じているので、CとC ++のいくつかの規則を述べたいだけです(これらに関しては同じです)。まず、のすべてのビットがunsigned char
、符号なしcharオブジェクトの値の決定に参加します。第二に、unsigned char
署名されていないことが明示的に述べられています。
ここで、-1
int型の値をに変換するとどうなるかについて誰かと話し合いましたunsigned char
。彼は、結果のunsigned char
すべてのビットが1に設定されているという考えを拒否しました。これは、彼が符号の表現について心配していたためです。しかし、彼はそうする必要はありません。変換が意図したとおりに行われるのは、このルールの直後です。
新しい型が符号なしの場合、値は、値が新しい型の範囲内になるまで、新しい型で表すことができる最大値よりも1だけ多く加算または減算することによって変換されます。(
6.3.1.3p2
C99ドラフト)
それは数学的な説明です。C ++では、同じ規則が得られるモジュロ計算の観点から説明しています。とにかく、整数のすべてのビットが変換前は1 であることは保証されていません-1
。それで、結果にunsigned char
はすべてのCHAR_BIT
ビットが1になっていると主張できるように、何がありますか?
UCHAR_MAX+1
する-1
と、範囲内の値、つまりUCHAR_MAX
実際はそれで十分です!つまり、unsigned char
すべてのビットを1にしたいときはいつでも、
unsigned char c = (unsigned char)-1;
また、変換では上位ビットが切り捨てられるだけではありません。2の補数の幸運な出来事は、単なる切り捨てであるということですが、他の符号表現については必ずしもそうではありません。
UCHAR_MAX
ですか?
(unsigned type)-1
イディオムのいくつかの種類です。~0
そうではありません。
int x = 1234
とchar *y = &x
。のバイナリ表現は1234
です00000000 00000000 00000100 11010010
。私のマシンはリトルエンディアンなので、逆にして、11010010 00000100 00000000 00000000
LSBを最初にメモリに格納します。今本編。私が使用する場合printf("%d" , *p)
。printf
最初のバイトを読みますと、11010010
出力のみである-46
が、11010010
ある210
、それは印刷しない理由そう-46
。私は本当に混乱しています.charからintegerへの昇格が何かをしていると思いますが、わかりません。
unsigned charの使用例として:
unsigned char
コンピュータグラフィックスでよく使用されます。(常にではありませんが)多くの場合、各カラーコンポーネントに1バイトを割り当てます。RGB(またはRGBA)カラーが24ビット(または32ビット)で表されるのが一般的unsigned char
です。以来unsigned char
の値が[0,255]の範囲に入る、値は典型的に解釈されます。
したがって、RGB赤は(255,0,0)->(100%赤、0%緑、0%青)になります。
なぜ使用しないのsigned char
ですか?算術演算とビットシフトは問題になります。すでに説明したように、a signed char
の範囲は基本的に-128シフトします。RGBをグレースケールに変換するための非常にシンプルで素朴な(ほとんど使用されていない)方法は、3つのカラーコンポーネントすべてを平均化することですが、これはカラーコンポーネントの値が負の場合に問題になります。unsigned char
算術を使用すると、赤(255、0、0)は平均して(85、85、85)になります。ただし、値がsigned char
s(127、-128、-128)の場合、最終的には(-99、-99、-99)となり、unsigned char
空間では(29、29、29)となりますが、これは正しくありません。 。
文字を短整数として使用したい場合、最も安全な方法はint8_t
およびuint8_t
タイプを使用することです。
int8_t
でuint8_t
はありません。また、オプションであり、バイトサイズが正確に8ビットではないアーキテクチャでは定義されていません。逆に、signed char
そしてunsigned char
少なくとも8ビットで常に利用可能と保持することが保証されています。一般的な方法かもしれませんが、最も安全ではありません。
signed char
とunsigned char
?それとも、その特定のケースでより良い「より安全な」代替手段をお勧めしますか?たとえば、「実際の」整数型に固執するためにsigned int
、unsigned int
代わりに何らかの理由で?
signed char
と、unsigned char
準拠するすべての実装に移植可能であり、ストレージスペースを節約できますが、コードサイズが多少大きくなる可能性があります。場合によっては、ビットフィールドまたは通常の整数型の単一ビットに小さな値を格納することで、より多くのストレージスペースを節約できます。この質問に対する絶対的な答えはありません。このアプローチの適切性は、目前の特定のケースに依存します。そして、この答えはとにかく質問に対処していません。
char
またunsigned char
、すべてのプラットフォームで8ビット型であるとは限りません。8ビット型以上であることが保証されています。一部のプラットフォームには、9ビット、32ビット、または64ビットのバイトがあります。ただし、現在最も一般的なプラットフォーム(Windows、Mac、Linux x86など)のバイト数は8ビットです。
アンは、unsigned char
符号なしバイト値(0〜255)です。あなたはchar
「キャラクター」であると考えているかもしれませんが、それは実際には数値です。レギュラーchar
は署名されているため、128個の値があり、これらの値はASCIIエンコーディングを使用して文字にマッピングされます。ただし、どちらの場合も、メモリに格納しているのはバイト値です。
直接値に関しては、値が中間CHAR_MIN
であることがわかっている場合に通常の文字が使用されCHAR_MAX
、符号なし文字の場合は正の端の範囲が2倍になります。たとえば、CHAR_BIT
が8の場合、レギュラーの範囲は[0、127 ]であることがchar
保証されます(署名付きまたは署名なしのため)unsigned char
。ただし、signed char
[0、255 ]であり、[-127、127]になります。
それが何のために使用されるかという点では、標準により、POD(プレーンな古いデータ)のオブジェクトをunsigned charの配列に直接変換できます。これにより、オブジェクトの表現とビットパターンを調べることができます。安全な型パンニングの同じ保証は、charまたはsigned charには存在しません。
unsigned char
ない、配列特異的に、および任意の「変換」は唯一の正式によって定義されるコピー実際の対象物から、宣言された配列のunsigned char
&次いで後者を検査します。ORがそのような配列として直接再解釈できるかどうか、ポインタの算術を考慮に入れて、つまり==
この使用法で「シーケンス」「配列」が可能かどうかは明確ではありません。これが明確になることを期待して開かれたコア問題#1701があります。ありがたいことに、最近この曖昧さが本当に私を悩ませています。
unsigned char
++ptr
memcpy
unsigned char
あらゆるトリックの中心です。ALLプラットフォームのほとんどすべてのコンパイラでunsigned char
は、これは単なるバイトであり、(通常)8ビットの符号なし整数であり、短整数またはビットのパックとして扱うことができます。
中毒では、誰かが言ったように、標準はcharの符号を定義していません。あなたが3つの異なる持っているchar
タイプを:char
、signed char
、unsigned char
。
unsigned charは、通常のcharの符号用に予約されているビットを別の数値として使用します。これにより、範囲が[-128-127]ではなく[0-255]に変更されます。
通常、署名が不要な場合は、署名されていない文字が使用されます。これは、ビットをシフトする(シフトが符号を拡張する)などのことや、charを数値として使用するのではなく、バイトとして扱う場合に違いをもたらします。
signed char
そして、unsigned char
の両方が1バイトを表しますが、彼らは異なる範囲を持っています。
Type | range
-------------------------------
signed char | -128 to +127
unsigned char | 0 to 255
ではsigned char
、我々は検討している場合char letter = 'A'
、「A」は65のバイナリを表すであるASCII/Unicode
65を格納することができた場合は、-65も保存することができます。に負のバイナリ値はありませんASCII/Unicode
負の値を気にする必要ありません。
例
#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;
}
出力-:
Signed char(255) : -1
Unsigned char(255) : 255
Signed char(-128) : -128
Unsigned char(-128) : 128