1

私は以下の小さなプログラムを書きました。

#include <stdio.h>
main(){
    char a=-1;
    unsigned char b=-1;
    printf("%d %d\n",a,b);
    printf("%x %x\n",a,b);
    if(a==b) printf("equal\n");
    else printf("not equal\n");
}

プログラムの出力は次のとおりです。

-1 255
ffffffff ff
not equal

char は 1 バイトのみで、-1 は 2 の補数形式で表されるため、a と b の両方に 0xff が格納されるため、両方が等しくなるはずです。なぜそれらが異なるのか、なぜ a の 16 進表現が 0xffffffff であり 0xff ではないのかを教えてください。関連リンクhttp://embeddedgurus.com/stack-overflow/2009/08/a-tutorial-on-signed-and-unsigned-integers/を取得しましたが、答えが得られませんでした。どんな助けでも大歓迎です。ありがとう。

4

4 に答える 4

5

それらは同じです。というか、基本的な表現は同じです (コンパイラが 2 の補数形式を使用するという仮定の下で)。

一方、それらが表す値は -1 と 255 です。

それらを印刷すると、データ型に拡張さintれます。unsigned charはゼロ拡張されていますが、signed char は符号拡張されており、これが違いを説明しています。

2 つの値を比較すると、同じ拡張が発生します。a == b基になる表現を比較しないでください。代わりに、両方の値を拡張して、int255 と -1 を比較しますが、これは等しくありません。

プレーンcharは、署名されているか署名されていない可能性があることに注意してください。あなたの環境では、明らかに署名されています。

于 2013-01-09T12:30:51.377 に答える
2

Asigned intは署名され、anunsigned intは署名されていません。just を使用する場合はint、 を意味しsigned intます。shortlongまたはについても同様ですlong long。しかし、それは真実ではありませんchar。Asigned charは署名され、 anunsigned charは署名されていませcharんが、署名されているか署名されていない可能性があります。データ型 char は「文字」を保持することになっているため、名前が付けられているため、計算で使用される整数を保持するのは「実際には」整数型ではありません。もちろん、文字は実際にはある種の整数ですが、その種類は実装に依存します (C 標準は特定の種類を強制しません)。したがって、整数値 (計算でも使用される) に char 型を使用する場合は、常にsigned charorunsigned charを明示的に使用し、単にchar実際に文字を扱っている場合、または char が署名されているか署名されていない場合でもコードにまったく違いがない場合。

char実装が be in fact と定義されているため、比較は失敗します。そのため、最終ステートメントでsigned charasigned charと anを比較しています。異なる型の 2 つの整数を比較する場合、コンパイラは、実際に比較を実行する前に、C 標準の規則に従って両方の値を同じ型に変換します。あなたの場合、これはCコンパイラが実際に次のことを行うことを意味します:unsigned charif

if((int)a==(int)b) printf("equal\n");
    else printf("not equal\n");
}

これで、これら 2 つの値が一致しない理由が明らかになったはずです。(int)aの値は です-1(int)b、 の値は255であり、これら 2 つの値は等しくありません。

タイプ Promotionの規則によれば、char(あなたの場合は signed) は に昇格されintunsigned charまた に昇格されintます。ISO C 2011 標準には、次のように記載されています。

int が元の型のすべての値を表すことができる場合 (ビットフィールドの幅によって制限されるため)、値は int に変換されます。それ以外の場合は、unsigned int に変換されます。これらは、整数昇格と呼ばれます。) 他のすべての型は、整数昇格によって変更されません。

整数昇格は、符号を含む値を保持します。前に説明したように、''プレーンな'' char が符号付きとして扱われるかどうかは処理系定義です。

于 2013-01-09T12:39:48.773 に答える
2

この型は、 orcharのいずれとも同じではないという点で異常です(明示的に宣言されていない限り、暗黙的に署名されている他の整数型 ( 、 、 など) とは異なります) 。が実際に署名されているかどうかは実装依存であり、一部のコンパイラでは、コマンド ライン スイッチを使用して署名を指定することさえできます。signed charunsigned charshortintlongunsignedchar

結論:charが符号付きまたは符号なしであると想定しないでください。実際に符号付きまたは符号なしの 8 ビット量が必要な場合は、signed charorunsigned charを明示的に使用するか、int8_tまたはuint8_tfromを使用することをお勧めします<stdint.h>

于 2013-01-09T12:26:43.767 に答える
0

単純な「char」(デフォルトでcharが署名されているか、署名されていないかを参照)にはあいまいさがありますが、ここで行われているのはそれだけではないと思います。

リテラル-1は整数であり、(引数のためにsizeof(int)> sizeof(char))文字に「適合」しません。2の補数ビットパターン0xffff(引数のために32ビットint)は切り捨てられ、ここにコピーされます。

printf()を呼び出すと、パラメーターは整数型にプロモートされ、符号付き型は「符号拡張」されますが、符号なし「b」はそうではなく、ゼロが埋め込まれます。2つの異なる型で「==」を使用すると、類似した(ただし必ずしも同一ではない)型変換が実行されます(別名「通常の算術変換」)。

C関数呼び出しおよび符号付きおよび符号なしのデフォルトの引数の昇格、およびCでのビット拡張の動作も参照してください。

于 2013-01-09T12:48:06.347 に答える