C言語のあれこれ3(基本的な値型の種類と構造体の作成方法)

2024/05/26に公開
6

はじめに

以下の記事の続きになります。
C言語のあれこれ1(Hello Worldの解読)

C言語のあれこれ2(変数と定数の作成方法)

こちらの記事から
実際に個人でコードを作成することができるように細かく説明するステップになります。

以下の順番で作成していきます。

  • 変数と定数の作成方法
  • 基本的な値型の種類と構造体の作成方法 <=今回の記事
  • 関数の作成方法
  • 計算するための演算子の説明
  • 条件に関する演算子と条件分岐、繰り返し文の作成方法
  • 配列を伴わないポインターの使用方法
  • 配列を伴ったポインターの使用方法

本編

ここでは基本的な値型の種類と構造体を記述します

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

yaito3014yaito3014

int 型にのみサイズが環境に依存することが明記されていますが、同様に short intlong int もそのサイズは環境依存となっています。
また C99 及び C++11 からは long long int なる整数型が追加されており、8バイト以上のサイズである保証があります。

齊藤敦志齊藤敦志

char型の時の最大値は127なのに対して

char が符号付きか符号無しかは処理系定義です。

アーキテクチャ (というか CPU) ごとになんとなく習慣として決まっていてインテル系だと符号付きが普通ですが ARM 系だと符号無しが普通です。

charsigned char とも unsigned char とも異なる独立した型としつつも signed charunsigned char のいずれかと同じ表現や動作をするという変則的な仕様となっています。

intsigned int は表記が違うだけで同じ型であるのに charsigned char ではないというのは奇妙な規則ですが歴史的事情があるようです。

そのため構造体のサイズは利用した変数のサイズの合計値になります。

メンバの間 (もしくは後ろ) に詰め物 (パディング) が入ることを許しています。 その分だけ合計より大きなサイズになることはあります。

ハードウェア的に特定の境界 (alignment) に合わせないと読み書きできないか、条件によっては大きな性能的ペナルティがある場合がありそこらを調整するためです。

定義した配列以上の値を配列から取り出そうとするとエラーが起きる

エラーになればむしろ有難いのですが C の言語仕様としては未定義です。

黙って不可解な挙動を引き起こすのは C ではよくあることなのでメモリ管理は慎重さが要ります。

Chronoss0518Chronoss0518

ご指摘ありがとうございます

char が符号付きか符号無しかは処理系定義です。

アーキテクチャ (というか CPU) ごとになんとなく習慣として決まっていてインテル系だと符号付きが普通ですが ARM 系だと符号無しが普通です。

こちらの仕様は初めて知りました。
一応ほかの方の参考資料のリンクも載せさせていただきます。
yohhoyの日記
Note(AyumiKatayama)

メンバの間 (もしくは後ろ) に詰め物 (パディング) が入ることを許しています。 その分だけ合計より大きなサイズになることはあります。

こちらも固定ではないのですね...
OS上のアプリケーションを作成することが以下に簡単か本当にありがたく感じますね。
JPCERTCC

今一度C言語で知らないことが多いと実感します。

改めてありがとうございます。

とがとが

long double が「C言語のバージョンアップにより追加された型」とされていますが,バージョンアップというのはいつを指していますか?最初の規格である C89 (ANSI C) から存在します.