複数の文字を保持するchar
配列があります。unsigned char
これらの文字の 1 つを変数と比較したいと考えています。例えば:
char myarr = { 20, 14, 5, 6, 42 };
const unsigned char foobar = 133;
myarr[2] = foobar;
if(myarr[2] == foobar){
printf("You win a shmoo!\n");
}
この比較型は安全ですか?
C99標準からchar
、 、signed char
、およびunsigned char
が 3 つの異なるタイプであることを知っています (セクション 6.2.5パラグラフ 14)。
- それにもかかわらず、精度を失うことなく、未定義 (または実装定義) の動作を危険にさらすことなく、 との間
unsigned char
を安全に変換できますか?char
セクション 6.2.5パラグラフ 15 :
実装は、 または のいずれかと同じ範囲、表現、および動作を持つように定義する
char
必要があります。signed char
unsigned char
セクション 6.3.1.3パラグラフ3:
それ以外の場合、新しい型は署名され、値を表現できません。結果が実装定義であるか、実装定義のシグナルが発生します。
残念ながら、 ifchar
が として定義されているsigned char
場合、元の値に正しく変換されない実装定義のmyarr[2] = foobar
値になる可能性があります。たとえば、関連する値に関係なく、実装は常に値になる場合があります。unsigned char
42
unsigned
- これは、同じ型
unsigned
の変数に値を格納するのは安全ではないということですか?signed
また、実装定義のシグナルとは何ですか。これは、この場合、実装が単にプログラムを終了できることを意味しますか?
セクション 6.3.1.1パラグラフ 1 :
- のランクは のランク
long long int
よりも大きく、 のランクよりlong int
も大きくなり、int
のランクよりもshort int
大きくなり、 のランクよりも大きくなりますsigned char
。-- 符号なし整数型のランクは、対応する符号付き整数型のランクと同じでなければなりません (存在する場合)。
セクション 6.2.5パラグラフ 8 :
符号が同じで整数変換ランクが異なる 2 つの整数型 (6.3.1.1 を参照) の場合、整数変換ランクが小さい方の値の範囲は、他の型の値の部分範囲になります。
セクション 6.3.1パラグラフ 2 :
int
が元の型のすべての値を表すことができる場合、値はint
;に変換されます。それ以外の場合は、に変換されますunsigned int
。
セクション 6.3.1.8パラグラフ 1 :
それ以外の場合、両方のオペランドは、符号付き整数型のオペランドの型に対応する符号なし整数型に変換されます。
の範囲は、またはchar
の範囲と同じであることが保証されています。これらは、 との部分範囲であり、整数変換ランクが小さいためです。signed char
unsigned char
int
unsigned int
整数昇格規則でchar
は、 、signed char
、およびunsigned char
が少なくとも評価される前に昇格されることが規定されているため、これは、比較全体でその「署名性」を維持できることをint
意味しますか?char
例えば:
signed char foo = -1;
unsigned char bar = 255;
if(foo == bar){
printf("same\n");
}
- 明示的なキャストが使用された場合と同等
foo == bar
であっても、偽の値に評価されますか?-1
255
(unsigned char)
更新:
セクション J.3.5パラグラフ1 で、どのケースが実装定義の値と動作になるかについて:
-- 値をその型のオブジェクトで表すことができない場合に、整数を符号付き整数型に変換した結果、またはそれによって生成されたシグナル (6.3.1.3)。
- これは、明示的な変換でさえ安全ではないということですか?
たとえば、次のコードは符号付き整数型char
として定義できるため、実装定義の動作になる可能性があります。
char blah = (char)255;