C言語のあれこれ3(基本的な値型の種類と構造体の作成方法)
はじめに
以下の記事の続きになります。
C言語のあれこれ1(Hello Worldの解読)
こちらの記事から
実際に個人でコードを作成することができるように細かく説明するステップになります。
以下の順番で作成していきます。
- 変数と定数の作成方法
- 基本的な値型の種類と構造体の作成方法 <=今回の記事
- 関数の作成方法
- 計算するための演算子の説明
- 条件に関する演算子と条件分岐、繰り返し文の作成方法
- 配列を伴わないポインターの使用方法
- 配列を伴ったポインターの使用方法
本編
ここでは基本的な値型の種類と構造体を記述します
int型
基本的な数値を入れる代表的な型です
int i_value = 0;
unsigned int型
int型の符号なし(+-がない)型になります。そのため負の値がなく、その分最大値が約2倍近く多くなります。
unsigned int ui_value = 0;
char型
端的に言えば1文字を格納するための型です。
サイズは1byte(8bit)になります。
char型には''で囲った1文字のみを入れるか、直接数値を入れることが可能です。
ここでは'\0' == 0を入れています
char c_value = '\0';
unsigned char型
char型の符号なし型になります。
かなりわかりやすく、char型の時の最大値は127なのに対してこちらは255(16進数だと0xff)まで入れることができます
unsigned char uc_value = '\0';
short型
こちらも整数を入れる型になります
short s_value = 0;
unsigned short型
short型の符号なし型になります。
unsigned short us_value = 0;
long型
整数型では最大の容量を誇る型です
long l_value = 0;
unsigned long型
long型の符号なし型になります。
unsigned long ul_value = 0;
整数型のサイズは基本的に以下のようになります。
char == unsigned cahr
< short == unsigned short
<= int == unsigned int
<= long == unsigned long
&&
short < long
float型
小数点の計算ができる浮動小数点型になります。
浮動小数点型には符号の有無の概念がないため、基本的にはすべて符号ありになります。
サイズは4byteになります。
float f_value = 0.0f;
double型
一番大きいメモリを利用する浮動小数点型になります。
サイズは8byteになります。
double d_value = 0.0;
long double型
double型よりも大きい浮動小数点型になります。
場合によってはdoubleと同じサイズになっていたりもします。
long double ld_value = 0.0;
C言語のバージョンアップにより追加された型
long long型
long型よりも大きい整数型になります。
long long ll_value = 0;
unsigned long long型
long long型の符号なし型になります。
unsigned long long ull_value = 0;
構造体
構造体は変数をまとめたものになります。
そのため構造体のサイズは基本的に利用した変数のサイズの合計値になります。
基本的な構文は次の通りです。
struct 構造体名
{
メンバー変数;
メンバー変数;
...
};
以下は例になります。
struct Test
{
int m_i_value;
double m_d_value;
char m_c_value;
};
構造体も通常の型と同じように宣言します。
struct 構造体名 変数名;
構造体のメンバー変数を利用する方法は次のように記述します。
変数名.メンバー変数
また構造体名は違う名前でも利用することが可能です。
方法は次の3種類になります。
#defineを利用する
#define TEST_STRUCT struct Test
TEST_STRUCT test;//-> struct Test test;
typedefを利用する1
typedef struct Test{}Test;
//typedef struct {}Test;でも可//
Test test;
typedefを利用する2(こちらの方法は値型でも利用可能です。)
typedef struct Test Test;
Test test;
配列の作成
配列は値型、構造体どちらでも利用することができます。
この時必ず配列の要素数を指定する必要があります。
配列のして方法は次の2つになります。
型名 変数名[配列数];
型名 変数名[] = {初期値,初期値...};
2つめの初期値は1個以上指定します。
int array[5];
int array2[] = {0,1,2,3,4,5};
配列から値を利用する場合は添え字を利用する必要があります。
取り出し方は次の通りです。
変数名[取り出す番号]
以下は使用例になります。
array[4];
この時取り出す番号は0番を先頭とした数字になります。
また、定義した配列以上の値を配列から取り出そうとするとエラーが起きるため、注意が必要です。
Discussion
int
型にのみサイズが環境に依存することが明記されていますが、同様にshort int
やlong int
もそのサイズは環境依存となっています。また C99 及び C++11 からは
long long int
なる整数型が追加されており、8バイト以上のサイズである保証があります。ご指摘ありがとうございます。
一部勘違いもあったため、こちらの内容は一旦削除するようにします。
参考資料 Oracle Help Center
参考資料2 Wikipedia
(環境の情報が媒体事に定まっていないように見え、shortとintは情報によってサイズが変わらない記述もあるためです)
char
が符号付きか符号無しかは処理系定義です。アーキテクチャ (というか CPU) ごとになんとなく習慣として決まっていてインテル系だと符号付きが普通ですが ARM 系だと符号無しが普通です。
char
はsigned char
ともunsigned char
とも異なる独立した型としつつもsigned char
かunsigned char
のいずれかと同じ表現や動作をするという変則的な仕様となっています。int
とsigned int
は表記が違うだけで同じ型であるのにchar
はsigned char
ではないというのは奇妙な規則ですが歴史的事情があるようです。メンバの間 (もしくは後ろ) に詰め物 (パディング) が入ることを許しています。 その分だけ合計より大きなサイズになることはあります。
ハードウェア的に特定の境界 (alignment) に合わせないと読み書きできないか、条件によっては大きな性能的ペナルティがある場合がありそこらを調整するためです。
エラーになればむしろ有難いのですが C の言語仕様としては未定義です。
黙って不可解な挙動を引き起こすのは C ではよくあることなのでメモリ管理は慎重さが要ります。
ご指摘ありがとうございます
こちらの仕様は初めて知りました。
一応ほかの方の参考資料のリンクも載せさせていただきます。
yohhoyの日記
Note(AyumiKatayama)
こちらも固定ではないのですね...
OS上のアプリケーションを作成することが以下に簡単か本当にありがたく感じますね。
JPCERTCC
今一度C言語で知らないことが多いと実感します。
改めてありがとうございます。
long double が「C言語のバージョンアップにより追加された型」とされていますが,バージョンアップというのはいつを指していますか?最初の規格である C89 (ANSI C) から存在します.
ご指摘ありがとうございます。
失礼しました。
これは完全に誤った情報になっているので削除します。
参考資料を追加させていただきます。