基礎について復習したかったので、家にある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