【C言語】アドレスとポインタ、動的確保

## アドレス
**アドレス**とは変数や関数等がメモリに保存されている場所

```C:example.c
#include <stdio.h>

int main(void)
{
    int tmp = 0;
    
    // &(アンパサンド)を宣言後の変数の前につけると、
    // アドレスが確認できる
    printf("変数 tmp のアドレス : %p\n", &tmp);
    
    return 0;
}
```

## ポインタ
**用途 : アドレス(変数や関数等がメモリに保存されている場所)を格納する**

- 宣言
```C
型 * 変数名;
```

- 定義
```C
変数名 = アドレス(&変数);
```

- アドレスに格納されている値
```C
*変数名
```

### 配列とポインタ
```C:example.c
#include <stdio.h>

int main(void)
{
    int iArray[5] = { 10, 8, 6, 4, 2, };
    
    // 配列の添え字番号を指定しない場合、
    // 変数は先頭のアドレス(今回はiArray[0])になる
    // ex)iArray == &iArray[0]
    int* p = iArray;
    
    // 配列の先頭から順に要素のアドレスと値を出力
    for (int i = 0; i < 5; i++, p++)
    {
        printf("アドレス : %p\n", p);
        printf("値 : %d\n", *p);
    }

    // 配列の先頭から、数字 * 型のサイズ分（iArray[0 + 数字]）アドレスの値を出力
    printf("配列[0 + 数字] の値 : %d\n", *(iArray + 数字));

    return 0;
}
```

### 構造体とポインタ
```C:example.c
#include <stdio.h>
#include <stdbool.h>

int main(void)
{
    struct Test
    {
        int a;
        int b;
        char c;
        float d;
        bool e;
    };
    struct Test t;

    struct Test* pTest = &t;
    pTest->a = 0;
    pTest->b = 10;
    pTest->c = '0';
    pTest->d = 0.0f;
    pTest->e = true;

    return 0;
}
```

※構造体のポインタは、.(ドット)ではなく、->(アロー)を用いる

### アドレス渡し
関数は通常、渡された引数の値をコピーして関数内に渡します(**値渡し**)。
ただし、関数内で引数の値を変更したい場合は、**アドレス渡し**を用います。
```C:example.c
#include <stdio.h>

/// <summary>
/// アドレスに格納されている値を1増やす
/// </summary>
/// <param name="_tmp">tmpのポインタ</param>
void Add(int* _tmp)
{
	*_tmp += 1;
}

int main(void)
{
	int tmp = 10;
	// アドレス渡し
	Add(&tmp);
	printf("tmp = %d\n", tmp);
	return 0;
}
```

## 参照(C++のみ)
`型&　変数名`
```C
int a = 10;
int &b = a; // bがaと同じメモリ領域にアクセス

b++; // aが11になる
```

抽象的に言うと、bとaは一心同体

### 参照渡し(C++、C#のみ)
- 用途
引数に`型&　変数名`を定義して、変数のメモリ上のアドレスを渡すことで、
関数内でその**変数の値を直接変更できる**ようにする。
アドレス渡しよりも手順が簡潔、かつ、アドレスの誤操作がなくなるため、
**安全性が高く**なる。

- C++
```C++
型 関数名(型& 変数名)...
```

- C#
```C#
型 関数名(ref 型 変数名)...
```

## メモリ領域(動的確保の前に...)
1. **グローバル領域・スタティック領域**
`グローバル変数やstatic(静的)な変数`が保存される
1. **スタック領域**
`自動変数`(関数内で宣言される変数等)が保存される
1. **ヒープ領域**
`動的確保`によって確保される

※ヒープ領域はプログラマー自身が明示的に解放しない限り`確保され続ける`
　解放を忘れると解放せずに終了(**メモリーリーク**)を起こす
　また、`解放したアドレスをプログラム上で触るとエラー`が起きる

## 動的確保(C/C++のみ)
**用途 : プログラマー自身で実行中のメモリを柔軟に管理する**
ex)スコープからの独立、複数の関数でメモリ領域の共有、メモリ領域を必要分のみ確保etc...
### mallocとfree
```C:example_malloc_free.c
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	// 動的確保
    // malloc : 確保されたメモリのアドレスをvoidポインタとして返す
	int* iPtr = (int*)malloc(sizeof(int));
	char* str = (char*)malloc(sizeof(char) * 32);

    // nullチェック
	if (iPtr == NULL)
	{
		printf("memory error\n");
		return -1;
	}

    // 数字を代入して、出力
	*iPtr = 10;
	printf("%d\n", *iPtr);

    // nullチェック
	if (str == NULL)
	{
		printf("memory error\n");
		return -1;
	}

    // 文字列を代入して、出力
	strcpy_s(str, 32, "Hello World");
	printf("%s\n", str);

	// メモリ領域の解放
	free(str);
	free(iPtr);

	return 0;
}
```
### newとdelete(C++、C#)
```C++:example_new_delete.cpp
#include <iostream>

int main(void)
{
	// 動的確保
	// new : 確保したオブジェクトのポインタを返す
	int* iPtr = new int;
	char* str = new char[32];

    // nullチェック
	if (iPtr == nullptr)
	{
		printf("memory error\n");
		return -1;
	}

    // 数字を代入して、出力
	*iPtr = 10;
    std::cout << *iPtr << std::endl;

    // 文字列を代入して、出力
	strcpy_s(str, 32, "Hello World");
    std::cout << str << std::endl;

	// メモリ領域の解放
	delete[] str; // 配列なので delete[]
	delete iPtr;  // 単一の要素なので delete

	return 0;
}
```
※C#の場合、ガベージコレクションがあるので、**deleteは不要**
### スマートポインタ(C++11以上)
`ポインタからの変更点 : メモリ管理の自動化(メモリリークの防止)`

スマートポインタには主に以下の三種類を指す
- std::unique_ptr(ユニークポインタ)
- std::shared_ptr(シェアードポインタ)
- std::weak_ptr(ウィークポインタ)

#### インクルード(#include)
`#include <memory>`

#### std::unique_ptr / std::shared_ptr共通
- 宣言
```C++
std::〇〇_ptr<型> 変数名;
```

- 定義
```C++
変数名.reset(new 型(値));
変数名.reset(new 型[要素数]); // 配列対応(C++17以降)
変数名 = std::make_〇〇<型>(値); // std::make_uniqueはC++14、std::make_sharedはC++11から
```

- 宣言・定義
```C++
std::〇〇_ptr<型> 変数名(new 型(値));

// 配列
std::unique_ptr<型[]> 変数名(new 型[要素数]);
std::shared_ptr<型> 変数名(new int[要素数], std::default_delete<int[]>());
std::unique_ptr<型[]> 変数名 = std::make_unique<int[]>(要素数); // 明示的な書き方(C++14以降)
std::shared_ptr<型[]> 変数名(new int[要素数]); // 配列対応(C++17以降)
std::shared_ptr<型[]> = std::make_shared<int[]>(10); // 明示的な書き方(C++20以降)

// テンプレート型の推論補助(C++17以降)
std::〇〇_ptr 変数名 = std::make_〇〇<型>(値);
```

- アドレスの取得
```C++
変数名.get();
```

- 明示的に解放(書かなくても良い)
```C++
変数名.reset();
```

#### std::unique_ptr
**std::unique_ptr**とは、あるメモリに対する所有権を持つポインタが、
ただ一つであることを保証するスマートポインタ

```C++
// 所有権の譲渡
// ※uPtr〇はstd::unique_prt型とする
uPtr2 = std::move(uPtr1);
```
#### std::shared_ptr
**std::shared_ptr**とは、同一のメモリの所有権を
複数で共有できるようにしたスマートポインタ
```C++
// 共有数の取得
// ※sPtrはstd::shared_prt型とする
sPtr.use_count();
```

#### 循環参照
`std::shared_ptrのメモリ解放`を行う場合、**共有数が0**ではない場合、**解放できない**。
それに伴い、`所有権を相互的に参照`(**循環参照**)した場合、**メモリリーク**が発生する。

#### std::weak_ptr
**用途 : 循環参照を防ぐ**
※循環参照を防ぐ安全性よりパフォーマンスを求める場合、生ポインタを推奨
　(オーバーヘッド等の理由により、生ポインタよりはパフォーマンスが下がるため)

 ```C++:example.cpp
#include <iostream>
#include <memory>

int main(void)
{
    // 弱参照
    std::shared_ptr<int> sPtr = std::make_shared<int>(10);
    std::weak_ptr<int> wPtr(sPtr);

    // 参照先のメモリが解放されていないなら
    if (!wPtr.expired())
    {
        // 所有権を共有する
        std::shared_ptr<int> sPtrTmp = wPtr.lock();
    }

    // 明示的な参照の終了(書かなくても良い)
    wPtr.reset();
    
    return 0;
}
 ```

### スマートポインタの参考記事
[C++20スマートポインタ入門](https://qiita.com/hmito/items/9b35a2438a8b8ee4b5af)

## 執筆者メモ
ポインタの仕様は複雑怪奇ですので、
何かご意見あれば、どしどしコメントお願いします!