【PHP日記】

自分の知識不足を悟った末、なるべく1日一回、Webに関する知識を書いていくだけのブログ。

データ型についての総括(C言語) 【4日目】

基礎について復習したかったので、家にあるC言語の教科書を引っ張り出して、まずはデータ型から見直していこうと思います。


データ型

4つの基本形

データ型には次の4つの基本型があります。どういう方のデータを扱うかによってデータ型を決めてやります。

データ型 データ 概要
char 文字 文字を表現するための型で、1バイト(8bit)の領域が確保される。数値も表現できる。
int 整数 整数を表現するための型で、ほとんどの処理系が4バイトの領域が確保される。
float 浮動小数点数 実数値を表現する型で、4バイトの領域が確保される。有効桁は7桁で(10進数でいうと)、±10³⁸まで表現できる。
double 浮動小数点数 floatと同様だが、8バイトの領域が確保される。有効桁が15桁程度で、範囲は±10³⁰⁸くらい。


int型についての補足(クリックで開く)

int型はシステムが得意とするデータサイズを確保するため、16bitコンピュータなら16bit、32bitコンピュータなら32bitになります。

ただし64bitコンピュターにおいては、int=8バイトとすると4バイトの整数型が無くなってしまい、また世の中にint=4バイトを前提としたソースコードが非常に多いため、int = 4バイトとなっている場合がほとんどです。


データ型の修飾子

データには、サイズ符号に対する修飾子をつけることが出来ます。サイズ修飾子はint型に対応しており、longはdouble型にも設定できます。


表. サイズ修飾子

修飾子 意味 宣言例 64bitにおけるサイズ
short 整数型が1、2バイトの領域になる short int a; 16bit
long 整数型が2、4バイトの領域になる long l; 64bit


表. 符号修飾子

修飾子 意味 宣言例
unsigned 符号なし(正の値のみ) unsigned int ui;
singned 符号あり(省略可) (signed) int si;


float型の解説

C言語で扱える実数値は、2進数の有限小数(いつか終わる少数)で表せる数値までです。

例)1.5(₁₀) = 1.1(₂)  ⭕️

例)0.1(₁₀) = 0.000110011001100110011...(₂) ✖️ 無限に続くため表せない


10進数の少数の2進数への直し方

2進数に変換したい値に×2して、繰り上がったら 1 を抜いてまた×2 する。
計算後の整数部をつなげた形が2進数の少数となる。
例) 0.8125*2=1.625、0.625*2=1.25、0.25*2=0.5、0.5*2=1、よって結果は0.1101


そのため非常に大きな(小さな)実数値を扱う場合は、仮数、および指数という概念を用いることで無駄な「000...」という桁数部分を省略しています。

例えば、「0.00000000001356923」という数字は「1356923 ﹡ 10⁻¹¹」と表すことができますが、この 1356923 に当たる部分を仮数といい、10⁻¹¹ に当たる部分を指数といいます。

そしてこれら概念に先頭1ビットである符号部分を合わせた値のことを浮動小数と呼びます。


また、float型は全体で32ビットのサイズを持っています。

その内部構造は先頭1ビットが符号部分、8ビットが指数部分、そして残りの23ビットが仮数部分を表しており、2進数の23桁(仮数)で表せる数値は10進数でいうところの約7桁になるため、float型で表せる有効桁数は7桁ということになります。


singnedの扱い上での注意

signedは、最上位のbitが負の値であることを意味する符号bitであるため、signed charに「1111 1111」という値を格納されている場合、10進数に変換すると「-128」になります。(正の値は「127」まで)


さらにsigned char型である「1101 1101」(10進数で表すと「-35」)を、short int(16bit)という別の型に代入した場合、中身は「1111 1111 1101 1101」となり、結果は同じく「-35」となります。

これは違う型への代入を行ったとき、元データが負の値の場合に限り最上位ビット「1」がコピーされるという仕組みになっているからです。


同様に、正の値である unsigned char型「1101 1101」(10進数で表すと「221」)を short int型に代入しても、元データが正の値なので上位に「0」が代入され、結果は同じく「0000 0000 1101 1101」(10進数で表すと「221」)になります。


ここまでなら問題ないのですが、もし違う型への代入を「負の値」「正の値」のようにしてしまうと、問題が発生します。

例えば、signed char型である「1101 1101」をunsigned short int型に代入してしまったとき、元データが負の値なので最上位ビット「1」がコピーされてしまい、結果「1111 1111 1101 1101」(10進数で表すと「65501」)という膨大な正の値となってしまいます。

これは「正の型」と「負の型」では、データの扱い方に違いがあるためです。


書式指定

C言語では、書式指定というどの形式のデータで読み込むか書き込むかを指定する必要があります。

これは受け取ったデータをどう扱うかを指定するため、受け取ったデータが何であろうが、指定された形式で扱われます。

形式は「変換文字列」と呼ばれ、printf関数、scanf関数の文字列の中などで使用します。


変換文字列 printf scanf
%o 符号なし8進数で 左と同じ
%d 10進数で 左と同じ
%x, %X 符号なし16進数で%xは小文字、%Xは大文字 符号なし16進数で
%u 符号なし10進数で 左と同じ
%f 10進数の浮動小数点で float型で
%lf - double型で
%c 文字として 左と同じ
%s 文字列として(文字列の先頭アドレスを呼び出す) 左と同じ


因みに書式指定で『表示桁数』を指定する場合は、『全体の幅. 小数点以下の幅』という形で指定します。

printf(" Double-Data : %14.13lf¥n", d);


以上です。



【参考文献】

https://www.cc.kyoto-su.ac.jp/~yamada/programming/float.html