見出し画像

C言語教室 第14回 - 変数型のサイズ

今まで整数であれば int 型を使っていましたが、整数型には扱える範囲の異なる型もあります。

まず、int 型は、その処理系にとって最も自然なサイズであるというのが C言語の定義で、具体的なサイズは処理系によって異なります。

short int は、int を省略して short として宣言することも出来ます。short int 型は int 型と同じか、より小さなサイズであると定義されています。

long int は、int を省略して long として宣言することもできます。long int 型は int 型と同じか、より大きなサイズであると定義されています。

加えて最近の処理系では、より大きな範囲を扱える long long int 型が追加されています。もちろん int を省略して long long と宣言することもできます。

この「最も自然なサイズ」というのがやっかいで、型の名前から具体的なサイズ(値の範囲)はわかりません。16ビットCPUの時は 2バイト(16ビット)であることが多く、32ビットの時代になって 4バイト(32ビット)が普通になったようですが、64ビットCPUであっても int は32ビットのままであることが多いようです。

変数の型とCPUの関係

その処理系がどのサイズの int を使っているかは、以下のコードで確認できます。

#include <stdio.h>

void main() {
  printf("SIZE=%d\n", sizeof(int));
}

いつものブラウザ環境では”SIZE=4”と出力されるので、int は 4バイト(32ビット)ですね。

特定のサイズが要求される場合には、処理系のよって適切な宣言が使われるように、型名を define で再定義したり、typedef で独自の型を作って、それを使うようにします。最近の C言語では、予め int32_t といった名前が用意されているようです。

もちろん short にも long にも符号なし型があり、これらは unsigned という予約語をさらに追加して宣言します。

unsigned short int v_usi;
unsigned long int v_uli;

さて数値を直接コードに埋め込むときにも、これらの型が関係します。int である時は、数値のままで良いのですが、末尾に “U” を付けると符号なし型となります。”L”を付けると long、”LL”を付けると long long の型を持ちます。

整数リテラル

異なるサイズの整数型が混在するときには、演算の途中で「暗黙の型変換」が発生することがあり、特に符号なし型がある場合には、かなりややこしい事態が発生します。

第5回 int型のサイズ

この話と値の最大、最小といった境界値が絡むと、以前の教室でも取り上げたようなややこしいバグが発生しがちです。

C言語の整数リテラルの謎【解説編】

サイズの異なる複数の整数型は、C言語に限った話ではなく、他の多くのプログラミング言語にも存在します。これらの間の型変換に関する注意点は、細かい差異はあるものの似たりよったりです。なかなかややこしいことが書いてありますが、特定のサイズに依存する時は、処理系によってサイズが変わらない型を使うようするのが良さそうです。

汎整数拡張

整数型


さて、サイズの異なる型が存在するのは、何も int だけではありません。ポインタ型に関しても、古のインテル86においては、メモリモデルというものが存在し、16ビットの near ポインタと、32ビットの far ポインタがありました(さらに huge もあります)。すべてが同じサイズのポインタであれば、さほど困らないのですが、汎用ライブラリ関数を呼び出すときなどに、ローカル変数で宣言した文字配列を引き数にするときなどに、near から far への型変換が必要になったり、ダブルポインタでメモリモデルが混在すると、char near* far* などという型が出てきたりすると、もう大変です。もうこのキーワードを見なくなったのは、とても幸せです。

さらに char に関しても、実は必ず 8ビットであるとは限らないようです。確かに 36ビットワードの大型機のCコンパイラが 9ビットで文字を表しているのは覚えているのですが、char が 16ビットと解釈される処理系もあるようです。

sizeof(char)==sizeof(int)となる処理系の奇妙な世界

そういえば、8ビット向け Cコンパイラで、int が 8ビットの実装があるにはあった記憶があるのですが、さすがにこれはダメだろうということで誰も使わなかったようです。

以下の說明が、これらをよくまとめてあります。

4.1.3 処理系依存

http://tool-support.renesas.com/autoupdate/support/onlinehelp/ja-JP/csp/V4.01.00/CS+.chm/Compiler-CCRL.chm/Output/cd_BASIC_LANG5.html


課題

long 型配列に格納されているランダムな数値を short 型配列にコピーしなさい。short に格納できない値が含まれているときには、short で表現できる最大値または最小値にすること。

演習

short、unsigned short、long、unsigned long 型の数値を printf で出力する時に使う書式指定子を調べなさい。

ヘッダ画像は、以下のサイトの素材から作成しました。
https://frame-illust.com/?p=1029

この記事が気に入ったらサポートをしてみませんか?