C の整数変数は 2 バイトまたは 4 バイトを占有しますか? それが依存する要因は何ですか?
ほとんどの教科書では、整数変数は 2 バイトを占めると書かれています。しかし、整数の配列の連続するアドレスを出力するプログラムを実行すると、4 の差が示されます。
に等しいことがわかっていsizeof(int)
ます。an のサイズint
は実際にはコンパイラに依存します。プロセッサが 16 ビットだった当時、anint
は 2 バイトでした。最近では、32 ビット システムでも 64 ビット システムでも、ほとんどの場合 4 バイトです。
それでも、sizeof(int)
プログラムが実行される特定のシステムの整数のサイズを取得するには、を使用するのが最善の方法です。
編集:int
ほとんどの 64 ビット システムで 8 バイトという間違ったステートメントを修正しました。たとえば、64 ビット GCC では 4 バイトです。
これは、最初は混乱する可能性がある C のポイントの 1 つですが、C 標準では、サポートされることが保証されている整数型の最小範囲のみを指定しています。int
-32767 ~ 32767 を保持できることが保証されており、これには 16 ビットが必要です。その場合、int
は 2 バイトです。int
ただし、多くの最新のコンパイラが32 ビットを作成することがわかるように、実装はその最小値を自由に超えることができます(これは、かなり遍在する 4 バイトも意味します)。
あなたの本が2バイトと言っている理由は、おそらくそれが古いからです。かつてはこれが当たり前でした。sizeof
一般に、使用しているプラットフォームでのバイト数を調べる必要がある場合は、常に演算子を使用する必要があります。
これに対処するために、C99 は、特定のサイズの整数を明示的に要求できる新しい型を追加しましint16_t
たint32_t
。それ以前は、特定の幅の整数を取得する普遍的な方法はありませんでした (ただし、ほとんどのプラットフォームはプラットフォームごとに同様の型を提供していました)。
C99 N1256 標準ドラフト
http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf
のサイズint
と他のすべての整数型は実装定義であり、C99 のみが指定します。
5.2.4.2.1「整数型のサイズ<limits.h>
」は、最小サイズを示しています。
1 [...] それらの実装定義の値は、示されているものと同じかそれ以上の大きさ (絶対値) でなければなりません [...]
- UCHAR_MAX 255 // 2 8 − 1
- USHRT_MAX 65535 // 2 16 − 1
- UINT_MAX 65535 // 2 16 − 1
- ULONG_MAX 4294967295 // 2 32 − 1
- ULLONG_MAX 18446744073709551615 // 2 64 − 1
6.2.5「タイプ」は次のように述べています。
8 符号が同じで整数変換ランクが異なる 2 つの整数型 (6.3.1.1 を参照) については、整数変換ランクが小さい方の値の範囲は、他の型の値の部分範囲です。
6.3.1.1「ブール値、文字、および整数」は、相対的な変換ランクを決定します。
1 すべての整数型には、次のように定義された整数変換ランクがあります。
- long long int のランクは long int のランクより大きくなければならず、long int のランクは int のランクより大きくなければならず、これは short int のランクより大きくなければならず、signed char のランクよりも大きくなければならない。
- 符号なし整数型のランクは、対応する符号付き整数型がある場合、そのランクと等しくなければなりません。
- すべての整数型 T1、T2、および T3 について、T1 のランクが T2 よりも高く、T2 のランクが T3 よりも高い場合、T1 のランクは T3 よりも高くなります。
C の整数変数は 2 バイトまたは 4 バイトを占有しますか?
これは、使用しているプラットフォームと、コンパイラの構成方法によって異なります。唯一の正式な答えは、sizeof
演算子を使用して、特定の状況での整数の大きさを確認することです。
それが依存する要因は何ですか?
sizeではなく、 range を考慮するのが最善かもしれません。どちらも実際には異なりますが、後で説明するように、サイズよりも範囲で変数の型を選択する方がはるかに簡単です。また、標準ではsizeではなくrangeに基づいて整数型を選択することを検討するよう奨励されていることに注意することも重要ですが、ここでは、標準的な慣行を無視して、好奇心で 、 bytes 、および integer 表現を探索しましょう...掘り下げてみましょううさぎの穴を見て、自分の目で確かめてください...sizeof
CHAR_BIT
sizeof
、バイトおよびCHAR_BIT
C 標準 (上記にリンク) から引用した次のステートメントは、これを改善できないと思われる言葉で説明しています。
この
sizeof
演算子は、そのオペランドのサイズ (バイト単位) を返します。これは、式または括弧で囲まれた型の名前の場合があります。サイズは、オペランドの型から決定されます。
明確に理解していると仮定すると、 bytesについての議論につながります。一般に、1バイトは 8 ビットであると想定されていますが、実際CHAR_BIT
には、1 バイトに含まれるビット数がわかります。これは、一般的な 2 (または 4) バイトの整数について話すときに考慮されないニュアンスの 1 つです。
これまでのことをまとめましょう。
sizeof
=> バイト単位のサイズ、およびCHAR_BIT
=> バイトのビット数したがって、システムによっては、16 であるかのように、0 より大きい (2 や 4 だけでなく)任意のsizeof (unsigned int)
値になる可能性があり、1 つの (16 ビット) バイトには、標準(以下に引用)。それは必ずしも有用な情報ではありませんね。もっと深く掘り下げてみましょう...CHAR_BIT
整数表現
C 標準では、すべての標準整数型 (およびCHAR_BIT
fwiw)の最小精度/範囲が指定されています。これから、値を格納するために必要なビット数の最小値を導き出すことができますが、範囲に基づいて変数を選択することもできます。それにもかかわらず、この回答に必要な詳細の大部分はここにあります。たとえば、次の場合、標準では (少なくとも) 16 ビットのストレージが必要です。unsigned int
UINT_MAX 65535 // 2¹⁶ - 1
したがって、(少なくとも)16ビットがunsigned int
必要であることがわかります。これは、2バイト(8であると仮定CHAR_BIT
)を取得する場所です...そして後でその制限が に増加したとき2³² - 1
、人々は代わりに4バイトを述べていました。これは、あなたが観察した現象を説明しています:
ほとんどの教科書では、整数変数は 2 バイトを占めると書かれています。しかし、整数の配列の連続するアドレスを出力するプログラムを実行すると、4 の差が示されます。
移植性のない C を教えている古代の教科書とコンパイラを使用しています。あなたの教科書を書いた著者は、CHAR_BIT
. 教科書 (およびコンパイラ)をアップグレードし、ITは絶えず進化する分野であり、競争に先んじる必要があることを忘れないように努めてください。基礎となる整数バイトが格納する他の移植不可能な秘密を見てみましょう...
値ビットは、一般的な誤解がカウントしているように見えるものです。上記の例では、unsigned
通常は値のビットのみを含む整数型を使用しているため、細部の悪魔を見逃すのは簡単です。
符号ビット... 上記の例では、コメントから値を抽出するのは簡単な例であるためUINT_MAX
、上限として引用しました。符号付きの型の場合、正の値と負の値 (符号) を区別するために、符号ビットも含める必要があります。unsigned int
16
INT_MIN -32768 // -(2¹⁵) INT_MAX +32767 // 2¹⁵ - 1
パディング ビット... 整数のパディング ビットを持つコンピュータに遭遇することは一般的ではありませんが、C 標準ではそれが可能です。一部のマシン (つまり、このマシン) は、2 つの小さい (符号付き) 整数値を組み合わせることにより、より大きな整数型を実装します。符号付き整数を組み合わせると、無駄な符号ビットが得られます。その無駄なビットは、C ではパディングと見なされます。パディング ビットの他の例には、パリティ ビットやトラップ ビットが含まれる場合があります。
ご覧のとおり、標準では、整数型を選択するときにINT_MIN
..INT_MAX
などの範囲や標準のその他の最小値/最大値を考慮することを推奨しているようであり、サイズに依存することを思いとどまらせCHAR_BIT
ています。の値に影響を与える可能性があります(つまり、 2 バイトおよび 4 バイトの整数sizeof (int)
に関する一般的な誤解により、これらの詳細が無視されます)。
唯一の保証は、少なくとも8 ビット幅でなけれchar
ばならず、少なくとも16 ビット幅でなければならず、少なくとも32 ビット幅でなければならず、<= <= <= (これらの型の符号なしバージョンについても同じことが当てはまります) です。 )。 short
int
long
sizeof (char)
sizeof (short)
sizeof (int)
sizeof (long)
int
プラットフォームに応じて、16 ~ 64 ビット幅のいずれかになります。
ほとんどの場合、使用しているプラットフォームに依存します。コンパイラからコンパイラに依存します。最近では、ほとんどのコンパイラでintは4 バイトです。コンパイラが何を使用しているかを確認したい場合は、 を使用できますsizeof(int)
。
main()
{
printf("%d",sizeof(int));
printf("%d",sizeof(short));
printf("%d",sizeof(long));
}
C コンパイラが約束する唯一のことは、short のサイズは int 以下でなければならず、long のサイズは int 以上でなければならないということです。 long と int についても同様です。また、ショートとロングのサイズを同じにすることはできません。
#include <stdio.h>
int main(void) {
printf("size of int: %d", (int)sizeof(int));
return 0;
}
これは 4 を返しますが、おそらくマシンに依存します。
しかし、この質問は、「はい。どちらも」という、常に正しい答えのようなものです。
アーキテクチャによって異なります。16 ビット以下のマシンで作業する場合は、4 バイト (=32 ビット) にすることはできません。32 ビット以上のマシンで作業している場合、その長さは 32 ビットです。
理解するには、プログラムを読み取り可能なものを出力する準備を整え、「sizeof」関数を使用します。これは、宣言されたデータ型のサイズをバイト単位で返します。ただし、これを配列で使用する場合は注意してください。
宣言している場合は、int t[12];
12*4 バイトが返されます。この配列の長さを取得するには、単に使用しますsizeof(t)/sizeof(t[0])
。送信配列のサイズを計算する関数を作成する場合は、次のことを覚えておいてください。
typedef int array[12];
int function(array t){
int size_of_t = sizeof(t)/sizeof(t[0]);
return size_of_t;
}
void main(){
array t = {1,1,1}; //remember: t= [1,1,1,0,...,0]
int a = function(t); //remember: sending t is just a pointer and equal to int* t
print(a); // output will be 1, since t will be interpreted as an int itselve.
}
したがって、これは別のものを返すことさえありません。配列を定義してから長さを取得しようとする場合は、sizeof を使用します。配列を関数に送信する場合、送信値は最初の要素へのポインターに過ぎないことに注意してください。ただし、場合によっては、配列のサイズを常に知っています。ケース 2 は、2 つの関数を定義することで解決できますが、パフォーマンスが低下します。function(array t) を定義し、function2(array t, int size_of_t) を定義します。"function(t)" を呼び出して、コピー作業によって長さを測定し、その結果を function2 に送信します。ここでは、可変配列サイズに対して必要なことを何でも実行できます。