0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

C言語の型についての学習

Posted at

今回の目的

今回もC言語の学習を進めていきます。今回はCにおける型について学習をしていきます。

Cにおける型の種類

C言語の主要なデータ型は、基本型派生型ユーザー定義型の3つに大きく分類できます。

基本型

型名 サイズ(一般的な環境) 説明
char 1バイト 1つの文字を格納します。ASCII文字を扱う際に使用されます。
int 4バイト 整数を格納します。最も一般的な整数型です。
float 4バイト 単精度浮動小数点数を格納します。小数点を含む数値を扱います。
double 8バイト 倍精度浮動小数点数を格納します。floatより高い精度が求められる場合に使用されます。
void N/A 値を持たないことを示します。関数の戻り値や引数がない場合、または汎用的なポインタとして使用されます。

まず最初に注意点があります。
上記のサイズ欄にて一般的な環境と記載してあるかと思いますが、基本形におけるバイト数は処理系、つまり実行環境により変わり一定のバイト数である保証がないためこのような記載をしています。なので使用する際も、予めバイト数に制限を持たせることはよろしくないようです。

/*バイト数の調べ方*/

printf("char..%d\n",(int)sizeof(char));

printf("int..%d\n",(int)sizeof(int));

printf("float..%d\n",(int)sizeof(float));

printf("double..%d\n",(int)sizeof(double));

結果(あくまで私の環境での結果です)

char..1
int..4
float..4
double..8

派生型

型名 説明
配列(Array) 同じ型の複数の要素を連続したメモリ領域に格納します。int array[5];のように宣言します。
ポインタ(Pointer) 変数のメモリ上のアドレスを格納します。int *ptr;のように宣言し、他の変数を間接的に操作できます。
関数(Function) 一連の処理をまとめたものです。データ型ではありませんが、関数のポインタとして扱われることがあります。

派生型

ポインタ型

ポインタ型は変数のメモリアドレスを格納する型で、間接的に他の変数にアクセスしたり、関数に変数のアドレスを渡す際に使用します。

    //ポインタのテスト
    int* p = NULL;//int型へのポインタ変数
    int i;
    i= 10;
    //iのアドレスをpに代入
    p = &i;

    //pの値
    printf("p = %p\n",p);
    //iの値
    printf("&i = %p\n",&i);

結果

p = 0x7fffffffd9f4
&i = 0x7fffffffd9f4
配列型

配列型は同じ型の複数の要素(メンバ)からなる型で、予め要素数を決めて宣言を行う。
(Cにも可変長配列(mallocとVLA)があるが、mallocについて勉強不足のためこちらも後日まとめて記事にします。一応VLAを使用した可変長配列の例だけ載せておきます。)
また、配列の要素に対してのポインタ経由でのアクセスも可能。

/*配列型*/
int array[5] = {10, 20, 30, 40, 50};
printf("*array = %d\n", *array); // 10
printf("array[3] = %d\n", array[3]); // 40
printf("*(array + 3) = %d\n", *(array + 3));//3つ目の要素に対してポインタ経由でアクセス

結果

*array = 10
array[3] = 40
*(array + 3) = 40
#include <stdio.h>
/*C99におけるVLA*/
	void sub(int size1,int size2, int size3){
    int var1;
    int array1[size1];
    int var2;
    int array2[size2][size3];
    int var3;

    printf("array1..%p\n",(void*)array1);
    printf("array2..%p\n",(void*)array2);
    printf("&var1..%p\n",(void*)&var1);
    printf("&var2..%p\n",(void*)&var2);
    printf("&var3..%p\n",(void*)&var3);
}
int main(void) {
    int size1,size2,size3;
    printf("整数を3つ入力してください\n");
    scanf("%d%d%d",&size1,&size2,&size3);
    sub(size1,size2,size3);
    return 0;
}
関数

データ型ではないが、こちらも配列と同様にポインタを宣言することが可能。
他の型との違いには以下のようなものがある。

  • 非オブジェクト型のため関数型の変数が存在しない
  • ポインタ型を除く他の型への派生ができない
    また、関数の戻り値に配列型は使用できない
#include <stdio.h>

/*引数に1.0を足して表示させる関数の宣言*/
void func1(double d){
printf("func1 + 1.0 = %f\n", d + 1.0);
}
/*引数に2.0を足して表示させる関数*/
void func2(double d){
printf("func2 + 2.0 = %f\n",d + 2.0);
}
int main(void){
/*関数へのポインタ宣言*/
void(*func_p)(double);

func_p = func1;
/*関数func1を直接呼び出し*/ 
func1(1.0);
/*関数ポインタ経由で関数func1を直接呼び出し*/ 
func_p(1.0);
/*関数func2を直接呼び出し*/
func2(1.0);
/*関数ポインタ経由で関数func2を直接呼び出し*/ 
func_p(1.0);

return 0;

}

結果

func1 + 1.0 = 2.000000
func2 + 2.0 = 3.000000

ユーザー定義型

型名 説明
構造体(struct 異なる型のデータを1つのまとまりとして扱います。関連する複数のデータをグループ化する際に便利です。
共用体(union 異なる型のデータが同じメモリ領域を共有します。メモリを節約したい場合に用いられますが、一度にアクセスできるのは1つのメンバだけです。
列挙型(enum 整数定数に名前をつけ、可読性を高めます。enum { RED, GREEN, BLUE };のように使用します。
typedef 既存のデータ型に別名(エイリアス)をつけます。複雑なデータ型をより分かりやすく表現するために使用されます。

こちらはまだ学習が追いついていないため、後日改めて記事にします。

まとめ

今回の学習を通じて派生型、特にポインタの重要性と特殊性を知った。
配列の要素や関数に対してポインタ経由でアクセスできるのは、これまで使ってきたjavaやPythonなどと大きく違うためとても勉強になった。

参照

0
0
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?