56

最近の宿題で、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

言い換えれば、私のシステムでは、intlongは同じであり、大きすぎて保持できないものは、大きすぎintて保持できませんlong

宿題自体はここでは問題ではありません。システムで を long にどのようint < longに割り当てればよいintのでしょうか?

この件に関して密接に関連する質問多数ある ことは承知していますが、これらの質問に対する回答だけでは、その過程で何が起こるか、または起こる可能性があるかを完全に理解することはできないと感じています.

基本的に私は次のことを理解しようとしています:

  1. 割り当ての前にキャストlongする必要がありますか、またはintlong 別のデータ型ではなく、単なる修飾子であるため、直接割り当てることは無害と見なされますか?
  2. システムで何が起こるlong > intか? 結果は未定義 (または予測不能) になりますか、それとも変数の余分な部分が省略されますか?
  3. longからへのキャストintはCでどのように機能しますか?
  4. キャストを使用しない場合、C での代入はどのようlongに機能しますか?int
4

2 に答える 2

46

int言語は、少なくとも 16 ビット、long少なくとも 32 ビットであり、表現できるすべての値を少なくともlong表現できることを保証します。int

longオブジェクトに値を割り当てるintと、暗黙的に変換されます。明示的なキャストは必要ありません。とにかく発生するのと同じ変換を指定するだけです。

あなたのシステムでは、intlongがたまたま同じサイズと範囲を持っている場合、変換は簡単です。値をコピーするだけです。

longが よりも広いシステムでint、値が に収まらない場合int、変換の結果は実装定義です。(または、C99 以降では、実装定義のシグナルを発生させることができますが、実際にそれを行うコンパイラは知りません。)通常発生するのは、上位ビットが破棄されることですが、依存するべきではありません。その上で。(符号なしの型では規則が異なります。符号付きまたは符号なしの整数を符号なしの型に変換した結果は明確に定義されています。)

オブジェクトに値を安全に代入する必要がある場合は、代入を行う前に値が適合するかどうかを確認できます。longint

#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 つの修正:intlongは、たまたま同じサイズと表現を持つ場合でも、常に異なる型です。算術型は自由に変換できるため、多くの場合、違いはありませんが、たとえばint*、 とlong*は別個の互換性のない型です。long*明示的な (そして潜在的に危険な) キャストなしでは、 aを anint*に、またはその逆に代入することはできません。

longまた、値をに変換する必要がある場合intは、最初にコードの設計を再検討する必要があります。このような変換が必要な場合もありますが、多くの場合、割り当て先の を最初にintとして定義する必要があるというサインです。long

于 2012-11-30T20:24:05.397 に答える
3

Alongは常に のすべての値を表すことができますint。割り当てた変数の型で手元の値を表すことができる場合、その値は保持されます。

表現できない場合、符号付きの宛先タイプの場合、結果は正式に指定されていませんが、符号なしの宛先タイプの場合、元の値 modulo 2 nとして指定されます。ここで、nは値表現のビット数です (これは必ず宛先のすべてのビット)。

実際には、最新のマシンでは、署名された型のラッピングも取得します。

これは、最新のマシンが2 の補数形式を使用して符号付き整数を表すためであり、「無効な値」などを表すために使用されるビット、つまり、値の表現に使用されるすべてのビットがありません。

nビット値表現では、任意の整数値xがx +K*2 nにマップされ、整数定数 K が選択され、結果が可能な値の半分が負の範囲になるように選択されます。

したがって、たとえば 32 ビットintでは、値 -7 はビットパターン番号 -7+2 32 = 2 32 -7 として表されるため、ビットパターンが表す数値を符号なし整数として表示すると、かなり大きな値が得られます。番号。

これが2 の補数と呼ばれる理由は、それが 2 進数システム、基数 2 数値システムにとって意味があるためです。2 進数システムには、1 の補数 (アポストロフィーの配置に注意してください) もあります。同様に、10 進数システムには、10 の補数と 9 の補数があります。4 桁の 10 の補数表現では、-7 を 10000-7 = 9993 と表します。これですべてです。

于 2012-11-30T20:36:56.673 に答える