最近の宿題では、long
変数を使用して結果を保存するように言われました。
私のシステム(インテルコアi5/64ビットWindows 7/gnu gccコンパイラー)で、私にとって本当に重要かどうかを確認することにし、次のコードを見つけました。
printf("sizeof(char) => %d\n", sizeof(char));
printf("sizeof(short) => %d\n", sizeof(short));
printf("sizeof(short int) => %d\n", sizeof(short int));
printf("sizeof(int) => %d\n", sizeof(int));
printf("sizeof(long) => %d\n", sizeof(long));
printf("sizeof(long int) => %d\n", sizeof(long int));
printf("sizeof(long long) => %d\n", sizeof(long long));
printf("sizeof(long long int) => %d\n", sizeof(long long int));
次の出力が生成されます。
sizeof(char) => 1
sizeof(short) => 2
sizeof(short int) => 2
sizeof(int) => 4
sizeof(long) => 4
sizeof(long int) => 4
sizeof(long long) => 8
sizeof(long long int) => 8
言い換えると、私のシステムでは、int
とlong
は同じであり、int
が保持するには大きすぎるものはlong
も保持します。
ここでは宿題の割り当て自体は問題ではありません。どのように、システム上で_int < long
、int
をlongに割り当てる必要がありますか?
あるある多数の近い関連する の質問この主題ですが、これらの答えは、プロセスの中で何が起こるか、または起こるかもしれないかについての完全な理解を私に提供しないと思います。
基本的に私は次のことを理解しようとしています:
long
をint
にキャストするか、または long
は異なるデータ型ではなく、単なる修飾子であるため、long > int
?結果は未定義(または予測不能)になりますか、それとも変数の余分な部分が省略されますか?long
からint
へのキャストはCではどのように機能しますか?long
からint
への割り当てはどのように機能しますか?この言語は、int
が少なくとも16ビット、long
が少なくとも32ビット、およびlong
が少なくともを表すことができることを保証します。 int
は表現できます。
long
値をint
オブジェクトに割り当てると、暗黙的に変換されます。明示的なキャストの必要はありません。とにかく起こる同じ変換を指定するだけです。
システムでは、int
とlong
のサイズと範囲が同じ場合、変換は簡単です。値をコピーするだけです。
long
がint
よりも広いシステムでは、値がint
に収まらない場合、変換の結果は実装で定義されます。 (または、C99以降、実装定義のシグナルを生成できますが、実際にそれを行うコンパイラーは知りません。)通常が起こるのは、高位ビットが破棄されることです。 、しかしそれに依存するべきではありません。 (符号なしの型では規則が異なります。符号付きまたは符号なし整数を符号なしの型に変換した結果は明確に定義されています。)
安全にlong
値をint
オブジェクトに割り当てる必要がある場合は、割り当てを行う前に値が収まることを確認できます。
#include <limits.h> /* for INT_MIN, INT_MAX */
/* ... */
int i;
long li = /* whatever */
if (li >= INT_MIN && li <= INT_MAX) {
i = li;
}
else {
/* do something else? */
}
「他の何か」の詳細は、あなたが何をしたいかに依存します。
1つの修正:int
とlong
は、同じサイズと表現を持っている場合でもalways別個のタイプです。算術型は自由に変換できるため、多くの場合、違いはありませんが、たとえばint*
とlong*
は明確で互換性のない型です。明示的な(および潜在的に危険な)キャストなしでは、long*
をint*
に割り当てることはできません。
long
値をint
に変換する必要がある場合、最初にすべきことは、コードの設計を再検討することです。そのような変換が必要な場合もありますが、多くの場合、割り当てられているint
が最初にlong
として定義されている必要があるという兆候です。
long
は、常にint
のすべての値を表すことができます。割り当てられた変数の型で手元の値を表すことができる場合、値は保持されます。
表現できない場合は、符号付き宛先タイプの場合、結果は形式的に指定されませんが、符号なし宛先タイプの場合は、2を法とする元の値として指定されますn、 どこ n 値表現のビット数です(宛先のすべてのビットとは限りません)。
実際には、最新のマシンでは、署名されたタイプのラッピングも行われます。
これは、最新のマシンが2の補数形式を使用して符号付き整数を表すためです。「無効な値」などを示すために使用されるビットはありません。
と n 任意の整数値のビット値表現 バツ にマップされます バツ+ K * 2n 結果が可能な値の半分が負になる範囲になるように整数定数Kを選択します。
したがって、たとえば、32ビットint
では、値-7はビットパターン番号-7 + 2として表されます32 = 232-7。ビットパターンが符号なし整数として表す数値を表示すると、かなり大きな数値が得られます。
これが2の補数と呼ばれる理由は、2進数の基数システムである2進数の数字システムにとって意味があるためです。 2進数システムの場合は、1の補数(アポストロフィの配置に注意)もあります。同様に、10進数システムでは、10の補数と9の補数があります。 4桁の10の補数表現では、-7は10000-7 = 9993として表されます。これですべてです。