unsigned charとは何ですか?


479

C / C ++では、何unsigned charが使用されますか?レギュラーとどう違うのchar

回答:


548

C ++には、3つの異なる文字タイプがあります。

  • char
  • signed char
  • unsigned char

テキストに文字タイプを使用している場合は、修飾なしを使用しますchar

  • 'a'orのような文字リテラルのタイプです'0'
  • それはCの文字列を構成するタイプです "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


4
明確にするために、32ビットの文字と32ビットの整数を使用でき、sizeof(int)!= sizeof(char)を使用できますか?標準でsizeof(char)== 1と記載されていますが、相対的なsizeof(int)は実際のサイズの違いまたは範囲の違いに基づいていますか?
ジョセフガービン

14
+1。しかし、C ++には4つの異なる文字タイプがあり、wchar_tはその1つです。
Eric Z

11
c ++ 11以降には、char、signed char、unsigned char、wchar_t、char16_t、char32_tの6つの異なる型があります。
marcinj 14

12
@unheilig sizeof関数ではなく演算子なので、後にスペースを置くのが一般的です。変数のサイズをとるときに括弧を省略すると、さらに良いスタイルになります。sizeof *pまたはsizeof (int)。これは、それが型または変数に適用される場合、すぐに明確になります。同様に、の後に括弧を置くことも冗長returnです。関数ではありません。
PatrickSchlüter2014年

3
char'a'またはのような文字リテラルのタイプです'0'。」C ++ではtrueですが、Cで'a'はありません。Cでは、ですint
chux-2016年

92

C標準ではの符号付きが定義されていないため、これは実装に依存しますchar。プラットフォームによっては、charがsignedまたはのunsigned場合があるため、明示的に要求するsigned charunsigned char、実装がそれに依存しているかどうかを確認する必要があります。charこれは、プラットフォームが文字列に入力するものと一致するため、文字列の文字を表す場合にのみ使用します。

違いsigned charとは、unsigned charあなたが期待通りです。ほとんどのプラットフォームでは、signed char範囲の8ビットの2の補数になり-128まで127、およびunsigned char8ビットの符号なし整数(あろう0255)。標準では、char型が8ビットである必要はなく、それだけがsizeof(char)返されることに注意してください1。あなたはと文字のビット数で取得することができますCHAR_BITlimits.h。ただし、これが以外のプラットフォームになる今日のプラットフォームはほとんどありませ8ん。

この問題の良い要約がここにあります

私がこれを投稿して以来他の人が述べたように、あなたは使用int8_tしたほうがよく、uint8_t本当に小さな整数を表現したいのなら。


2
signed char型は-128から127までではない、-127〜127の唯一の最小範囲を有する
12431234123412341234123

3
@ 12431234123412341234123:技術的には真であり、C標準では-127〜127が最小範囲として定義されています。ただし、2の補数演算を使用しないプラットフォームを見つけるように要求します。ほぼすべての近代的なプラットフォームでは、署名した文字の実際の範囲は-128〜127になります
トッドギャンブリン

CHAR_BIT規格では少なくとも8ビットである必要があります。
martinkunev

39

私はそれが本当に求められていると感じているので、CとC ++のいくつかの規則を述べたいだけです(これらに関しては同じです)。まず、のすべてのビットunsigned char、符号なしcharオブジェクトの値の決定に参加します。第二に、unsigned char署名されていないことが明示的に述べられています。

ここで、-1int型の値をに変換するとどうなるかについて誰かと話し合いましたunsigned char。彼は、結果のunsigned charすべてのビットが1に設定されているという考えを拒否しました。これは、彼が符号の表現について心配していたためです。しかし、彼はそうする必要はありません。変換が意図したとおりに行われるのは、このルールの直後です。

新しい型が符号なしの場合、値は、値が新しい型の範囲内になるまで、新しい型で表すことができる最大値よりも1だけ多く加算または減算することによって変換されます。(6.3.1.3p2C99ドラフト)

それは数学的な説明です。C ++では、同じ規則が得られるモジュロ計算の観点から説明しています。とにかく、整数のすべてのビットが変換前は1 であることは保証されていませ-1。それで、結果にunsigned charはすべてのCHAR_BITビットが1になっていると主張できるように、何がありますか?

  1. すべてのビットがその値の決定に関与します。つまり、オブジェクトでパディングビットは発生しません。
  2. に1回だけ追加UCHAR_MAX+1する-1と、範囲内の値、つまりUCHAR_MAX

実際はそれで十分です!つまり、unsigned charすべてのビットを1にしたいときはいつでも、

unsigned char c = (unsigned char)-1;

また、変換では上位ビットが切り捨てられるだけではありません2の補数の幸運な出来事は、単なる切り捨てであるということですが、他の符号表現については必ずしもそうではありません。


2
なぜ使用しないのUCHAR_MAXですか?
ニコラス

1
そのため(unsigned type)-1イディオムのいくつかの種類です。~0そうではありません。
PatrickSchlüter2014年

1
私はこのような何かを持っている場合int x = 1234char *y = &x。のバイナリ表現は1234 です00000000 00000000 00000100 11010010。私のマシンはリトルエンディアンなので、逆にして、11010010 00000100 00000000 00000000LSBを最初にメモリに格納します。今本編。私が使用する場合printf("%d" , *p)printf最初のバイトを読みますと、11010010出力のみである-46が、11010010ある210、それは印刷しない理由そう-46。私は本当に混乱しています.charからintegerへの昇格が何かをしていると思いますが、わかりません。
Suraj Jain

27

unsigned charの使用例として:

unsigned charコンピュータグラフィックスでよく使用されます。(常にではありませんが)多くの場合、各カラーコンポーネントに1バイトを割り当てます。RGB(またはRGBA)カラーが24ビット(または32ビット)で表されるのが一般的unsigned charです。以来unsigned charの値が[0,255]の範囲に入る、値は典型的に解釈されます。

  • 0は、特定の色成分がまったくないことを意味します。
  • 255は、特定のカラー顔料の100%を意味します。

したがって、RGB赤は(255,0,0)->(100%赤、0%緑、0%青)になります。

なぜ使用しないのsigned charですか?算術演算とビットシフトは問題になります。すでに説明したように、a signed charの範囲は基本的に-128シフトします。RGBをグレースケールに変換するための非常にシンプルで素朴な(ほとんど使用されていない)方法は、3つのカラーコンポーネントすべてを平均化することですが、これはカラーコンポーネントの値が負の場合に問題になります。unsigned char算術を使用すると、赤(255、0、0)は平均して(85、85、85)になります。ただし、値がsigned chars(127、-128、-128)の場合、最終的には(-99、-99、-99)となり、unsigned char空間では(29、29、29)となりますが、これは正しくありません。 。


13

文字を短整数として使用したい場合、最も安全な方法はint8_tおよびuint8_tタイプを使用することです。


2
良い考えint8_tuint8_tはありません。また、オプションであり、バイトサイズが正確に8ビットではないアーキテクチャでは定義されていません。逆に、signed charそしてunsigned char少なくとも8ビットで常に利用可能と保持することが保証されています。一般的な方法かもしれませんが、最も安全ではありません。
chqrlie 2015

2
これはコメントであり、質問の答えにはなりません。
ランディン2017年

@chqrlieつまり、メモリを節約したい場合、小さな整数を表す最も安全な方法は、signed charunsigned char?それとも、その特定のケースでより良い「より安全な」代替手段をお勧めしますか?たとえば、「実際の」整数型に固執するためにsigned intunsigned int代わりに何らかの理由で?
RobertSがモニカチェリオをサポート

@ RobertS-ReinstateMonica:を使用するsigned charと、unsigned char準拠するすべての実装に移植可能であり、ストレージスペースを節約できますが、コードサイズが多少大きくなる可能性があります。場合によっては、ビットフィールドまたは通常の整数型の単一ビットに小さな値を格納することで、より多くのストレージスペースを節約できます。この質問に対する絶対的な答えはありません。このアプローチの適切性は、目前の特定のケースに依存します。そして、この答えはとにかく質問に対処していません。
chqrlie

10

unsigned char正の値のみを取ります... 0から255のように

どこに

signed char正と負の両方の値を取ります... -128のように +127など


9

charまたunsigned char、すべてのプラットフォームで8ビット型であるとは限りません。8ビット型以上であることが保証されています。一部のプラットフォームには、9ビット、32ビット、または64ビットのバイトがあります。ただし、現在最も一般的なプラットフォーム(Windows、Mac、Linux x86など)のバイト数は8ビットです。


8

signed char 範囲は-128から127です。 unsigned char範囲は0〜255です。

char コンパイラーに応じて、signed charまたはunsigned charと同等ですが、特殊なタイプです。

Cスタイルの文字列を使用している場合は、単にを使用しますchar。算術演算にcharsを使用する必要がある場合(かなりまれ)、移植性のために明示的に符号付きまたは符号なしを指定します。


8

アンは、unsigned char符号なしバイト値(0〜255)です。あなたはchar「キャラクター」であると考えているかもしれませんが、それは実際には数値です。レギュラーcharは署名されているため、128個の値があり、これらの値はASCIIエンコーディングを使用して文字にマッピングされます。ただし、どちらの場合も、メモリに格納しているのはバイト値です。


7

直接値に関しては、値が中間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には存在しません。


実際には、ほとんどの場合[-128、128]です。
ラスタジェダイ

標準のみ正式としてオブジェクト表現を定義する配列unsigned charない、配列特異的に、および任意の「変換」は唯一の正式によって定義されるコピー実際の対象物から、宣言された配列unsigned char&次いで後者を検査します。ORがそのような配列として直接再解釈できるかどうか、ポインタの算術を考慮に入れて、つまり==この使用法で「シーケンス」「配列」が可能かどうかは明確ではありません。これが明確になることを期待して開かれたコア問題#1701があります。ありがたいことに、最近この曖昧さが本当に私を悩ませています。
underscore_d

1
@RastaJediいいえ、ありません。できません。-128 ... + 128の範囲は、8ビットで表すことは物理的に不可能です。その幅は2 ^ 8 == 256の離散値のみをサポートしますが、0 = 257の場合は-128 ... + 128 = 2 * 128 + 1です。符号の大きさの表現は-127 ... + 127を許可しますが、2(双極)を持ちますゼロ。2の補数表現は、単一のゼロを維持しますが、負の側にもう1つの値を持つことで範囲を構成します。-128 ... + 127を許可します。(より大きなビット幅の両方で同様です。)
underscore_d

私の2番目のコメントについて、最初のOR へのポインターを取得し、そこから使用してそのすべてのバイトを読み取ることができると想定するのは理にかなっています...それは、ジグソーパズルのような、スタンダードの他の多くの節(そして多くの点での単なる存在)からは「おそらく大丈夫」だと推測するために残されました。これは理想的ではありません。ええと、多分言い回しは改善されるでしょう。これが私が言及したCWGの問題ですが、リンクするスペースがありませんでした-open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1701unsigned char++ptrmemcpy
underscore_d

@underscore_d申し訳ありませんが、それはタイプミスでした。[-128、127]は、私が:pと入力するつもりでした。ええ、私は符号/大きさの二重ゼロ(「正」と「負」のゼロ)について知っています。疲れたに違いない。
ラスタジェダイ2016

5

unsigned charあらゆるトリックの中心です。ALLプラットフォームのほとんどすべてのコンパイラでunsigned charは、これは単なるバイトであり、(通常)8ビットの符号なし整数であり、短整数またはビットのパックとして扱うことができます。

中毒では、誰かが言ったように、標準はcharの符号を定義していません。あなたが3つの異なる持っているcharタイプを:charsigned charunsigned char


1
ビットトリック、別名ビットトゥウィドリングまたはビットハッキングは、依存症を引き起こすことが実際に知られています;-)
chqrlie

3
問題を引き起こすのは0です。いじりから中毒を避けるために、いたずらっ子から離れてください。
DragonLord 2016年

5

あなたの特定の長さと符号の有無の様々なタイプを使用してのような場合は、おそらくより良いオフにしているuint8_tint8_tuint16_tなど、彼らが言う正確に何をすべきかというだけの理由。


4

何人かのグーグルがこれを見つけ、人々はこれについて議論しました。

unsigned charは基本的に1バイトです。したがって、1バイトのデータが必要な場合にこれを使用します(たとえば、Windows APIでよく行われるように、フラグをオンおよびオフにして関数に渡すように設定したい場合など)。


4

unsigned charは、通常のcharの符号用に予約されているビットを別の数値として使用します。これにより、範囲が[-128-127]ではなく[0-255]に変更されます。

通常、署名が不要な場合は、署名されていない文字が使用されます。これは、ビットをシフトする(シフトが符号を拡張する)などのことや、charを数値として使用するのではなく、バイトとして扱う場合に違いをもたらします。


4

unsigned char正の値のみをsigned char取る:0から255、正と負の値を 取る:-128から+127。


3

「Cプログラミングのラグージ」本から引用:

修飾子signedまたははunsignedcharまたは任意の整数に適用することができます。符号なしの数値は常に正またはゼロであり、2 ^ nを法とする算術の法則に従います。ここで、nは型のビット数です。したがって、たとえば、charが8ビットの場合、unsigned char変数は0〜255の値を持ち、signed charは-128〜127の値を持ちます(2の補数のマシンで)。に依存しますが、印刷可能な文字は常に正です。


2

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/Unicode65を格納することができた場合は、-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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.