C++ 参照渡しの勉強 ② ポインタ渡し

　前回、構造体の値渡しの勉強をしました。
　プログラムを少し改造します。
 　CPUの情報を読み取る部分も関数にします。
  
```works4.cpp
#include <iostream>
#include <string>
#include <fstream>

struct cpuInfo {
    std::string User;
    std::string System;
    std::string Idle;
};

float getCpuInfoData(struct cpuInfo data);

int  main(){

    cpuInfo info = {"123","234","345"};
    getCpuInfoData(info);
    std::cout << "user:" << info.User << std::endl;
    std::cout << "system:" << info.System << std::endl;
    std::cout << "idle:" << info.Idle << std::endl;

    return 0;
}

float  getCpuInfoData(struct cpuInfo info){
    std::cout << "\n in subroutine getCpuInfoData " << std::endl;

    std::ifstream ifs("/proc/stat");
    std::string firstCpuData;

    if (ifs.fail()) {
        std::cerr << "Failed to open file." << std::endl;
        return -1;
    }
    getline(ifs, firstCpuData);
    ifs.close();
    std::cout << firstCpuData << std::endl;

    firstCpuData = firstCpuData.substr(5);
    std::string user = firstCpuData.substr(0,firstCpuData.find(" "));
    firstCpuData = firstCpuData.substr(user.size()+1);

    std::string nice = firstCpuData.substr(0,firstCpuData.find(" "));
    firstCpuData = firstCpuData.substr(nice.size()+1);

    std::string system = firstCpuData.substr(0,firstCpuData.find(" "));
    firstCpuData = firstCpuData.substr(system.size()+1);

    std::string idle = firstCpuData.substr(0,firstCpuData.find(" "));
    firstCpuData = firstCpuData.substr(idle.size()+1);

    info.User = user;
    info.System = system;
    info.Idle = idle;

    std::cout << "user:" << info.User << std::endl;
    std::cout << "system:" << info.System << std::endl;
    std::cout << "idle:" << info.Idle << std::endl;

    float total = std::stof(info.User) + std::stof(info.System) + std::stof(info.Idle);
    std::cout << "\ntotal  " << total << std::endl;
    std::cout << "user %   " << (std::stof(info.User) / total) * 100 << std::endl;
    std::cout << "system % " <<(std::stof(info.System) / total) * 100 << std::endl;
    std::cout << "idle %   " << (std::stof(info.Idle) / total) * 100 << std::endl;


    std::cout << "\nreturn \n\n";
    return 0;
}
 ```
　実行します。
 ```
$ g++ works4.cpp -o auto
$ ./auto

 in subroutine getCpuInfoData
cpu  49074 1623 30936 60293708 8927 0 25 0 0 0
user:49074
system:30936
idle:60293708

total  6.03737e+07
user %   0.0812837
system % 0.0512408
idle %   99.8675

return

user:123
system:234
idle:345
```
　実行しました。関数内ではそれぞれの数値は表示されましたが、mainでは、値が初期化した状態のままです。
 　で、構造体をさすポインタを使わないと、内容を変更？アップデートできないようです。
  当たり前？

### 本命のポインタ渡しでGo

  そもそも　変数の場合は、
- ポインタ渡しは変数のメモリ上のアドレスを渡す記法

わからん。

- 渡されたアドレスを間接参照する

もっとわからん

　変数の頭に&をつけるとアドレスを表すそうだ。
 
```works5.cpp
#include <iostream>

int main(){

    float cpu_niceData = 3.14;
    std::cout << cpu_niceData << std::endl;
    std::cout << &cpu_niceData << std::endl;

    return 0;
}
```
　動かすと、変数の値とアドレスを表示します。
```
$ g++ works5.cpp -o auto
$ ./auto
3.14
0xffffdcd1b9b4
```
　アドレス0xffffdcd1b9b4に、3.14が収納されているという解釈らしいです。3.14はそのままなんだろうか？いえ、ほとんどの例題で使われるintと違って、floatは内部形式が「IEEE754 単精度浮動小数点数の形式：binary32」になっているはずです。確かめてみましょう。
 
```works5.cpp
#include <iostream>
#include <iomanip>
#include <ostream>

int main(){

    union { float cpu_niceData; int32_t i; } a;

    a.cpu_niceData = 3.14;
    int32_t i;

    std::cout << a.cpu_niceData << std::endl;

    std::cout << "内部形式 " << std::hex << std::setw(8) << std::setfill('0')
              << std::showbase << a.i << std::endl;

    std::cout << "アドレス " << &a.cpu_niceData << std::endl;

    return 0;
}
```
　コンパイルして実行します。
 
```
$ g++ works5.cpp -o auto
$ ./auto
3.14
内部形式 0x4048f5c3
アドレス 0xffffd2d97360
```
　内部形式を、

 https://gregstoll.dyndns.org/~gregstoll/floattohex/

 　ここで確かめます。「IEEE754 単精度浮動小数点数の形式：binary32」で正しいようですね。
 
![pointer100.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/28c0fd38-159b-07a9-3d17-cf4fc9f6a653.png)

 寄り道しましたが、
 「0xffffd2d97360」というのが、
 - 変数cpu_niceDataの値である0x4048f5c3
 - 
 という値が入っているアドレスを指します。
 　わかりにくい、いやわからん。
 　世の中、整数で話が解説されているので、そちらも参照してください。
  
##### アドレスはわかった。ハンドリングは「*」を使う

　そもそも　ポインタを使って、アドレスをいじるのが何のメリットになるかという点が説明されていないような。。。気がする。

　今までと同様に、まず、変数を用意します。変数の名前はcpu_niceDataで、変数の値は3.14です。
```
    float cpu_niceData = 3.14;
    std::cout << cpu_niceData << std::endl;
```
　アドレスは、&cpu_niceDataです。
 ```
     std::cout << &cpu_niceData << std::endl;
```
　次はポインタ変数です。**ポインタ変数にはアドレス**を入れるのだそうです。

>アドレスをもっている変数を**ポインタ変数**と言います

>ポインタ変数とはそもそも、参照したい変数をアドレスを使って呼び出すというのが目的なので、変数自体には参照したい変数のアドレスを入れる必要があるため

という説明があるのですが、わからん。頭に入ってこない。
```
int* pointer_for_cpu_niceData = &cpu_niceData;
```
　ポインタ変数pointer_for_cpu_niceDataは、単にポインタと呼ばれることがあります。
 　え、だめ、型が異なるとだめな？？？
```
float* pointer_for_cpu_niceData = &cpu_niceData;
```

 　ここまでが宣言？定義？で、計算は、次のようになります。

>＊は間接演算子と呼ばれます。
>間接演算子 * を使うと、そのポインタが指す変数の値を取り出すことができます。

  ポインタ pointer_for_cpu_niceData が指す変数に 3.14 * 10の計算結果を代入するという事例です。
```
  * pointer_for_cpu_niceData = 3.14 * 10
```
　ここまでを動かしてみます。

```works5.cpp
#include <iostream>
#include <iomanip>
#include <ostream>

int main(){

    union { float cpu_niceData; int32_t i; } a;

    a.cpu_niceData = 3.14;
    int32_t i;

    std::cout << a.cpu_niceData << std::endl;

    std::cout << "内部形式 " << std::hex << std::setw(8) << std::setfill('0')
              << std::showbase << a.i << std::endl;

    std::cout << "アドレス " << &a.cpu_niceData << std::endl;

    float* pointer_for_cpu_niceData = &a.cpu_niceData;

    std::cout << "Pointerから変数の値を参照 " << *pointer_for_cpu_niceData << std::endl;

    *pointer_for_cpu_niceData = 3.14 * 10;  // ポインタ pointer_for_cpu_niceData が指す変数に計算結果を代入

    std::cout << "Pointerから変数の値を参照 " << *pointer_for_cpu_niceData << std::endl;

    return 0;
}
```
　実行します。元の変数を10倍した値を代入できました。けど、これが何の役に立つのかは、現時点で不明です。めんどうなだけです。
```
$ g++ works5.cpp -o auto
$ ./auto
3.14
内部形式 0x4048f5c3
アドレス 0xffffde38e648
Pointerから変数の値を参照 3.14
Pointerから変数の値を参照 31.4
```

##### 関数を使う
　関数で、ポインタ pointer_for_cpu_niceData が指す変数を更新してみます。
 　関数名はmultiCpuで、何も値を返さないので、voidにしました。

```works6.cpp
#include <iostream>
#include <iomanip>
#include <ostream>

void multiCpu(float *pointer_for_cpu_niceData){
    *pointer_for_cpu_niceData = *pointer_for_cpu_niceData *100;
}


int main(){

    float cpu_niceData = 3.14;

    std::cout << cpu_niceData << std::endl;

    std::cout << "アドレス " << &cpu_niceData << std::endl;

    float* pointer_for_cpu_niceData = &cpu_niceData;

    std::cout << "orgin Pointerから変数の値を参照 " << *pointer_for_cpu_niceData << std::endl;

    *pointer_for_cpu_niceData = 3.14 * 10;  // ポインタ pointer_for_cpu_niceData が指す変数に計算結果を代入

    std::cout << "main Pointerから変数の値を参照 " << *pointer_for_cpu_niceData << std::endl;

    multiCpu(&cpu_niceData);
    std::cout << "function Pointerから変数の値を参照 " << *pointer_for_cpu_niceData << std::endl;

    return 0;
}
```
　実行します。
```
$ g++ works6.cpp -o auto
$ ./auto
3.14
アドレス 0xffffcfe54dcc
orgin Pointerから変数の値を参照 3.14
main Pointerから変数の値を参照 31.4
function Pointerから変数の値を参照 3140
```
　``*pointer_for_cpu_niceData``は、関数内で更新されて、mainに戻ると、その更新された値が表示されました。
 　ポインタ、ポインタ変数を使うと、main内、関数のどちらでも、変数の更新ができました。けど、値渡しでも同じことはできる？ような気がしますが。できないんだっけ。

##### 構造体を関数で使う
　構造体でも、変数のときと、ポインタの扱い方、表現方法は同じです。
 　構造体のメンバへの代入が、ドットではなく、->に代わります。何度見ても、矢印の方向が逆のような気がしてなりません。
  　最初の値渡しの、構造体の各メンバが更新されないプログラムを、ポインタを使った形に書き換えました。
   

```works4p.cpp
#include <iostream>
#include <string>
#include <fstream>

struct cpuInfo {
    std::string User;
    std::string System;
    std::string Idle;
};

float getCpuInfoData(struct cpuInfo* data);

int  main(){

    cpuInfo info = {"123","234","345"};

    getCpuInfoData(&info);

    std::cout << "main user:" << info.User << std::endl;
    std::cout << "main system:" << info.System << std::endl;
    std::cout << "main idle:" << info.Idle << std::endl;

    return 0;
}

float  getCpuInfoData(struct cpuInfo* info){
    std::cout << "\n in subroutine getCpuInfoData " << std::endl;

    std::ifstream ifs("/proc/stat");
    std::string firstCpuData;

    if (ifs.fail()) {
        std::cerr << "Failed to open file." << std::endl;
        return -1;
    }
    getline(ifs, firstCpuData);
    ifs.close();
    std::cout << firstCpuData << std::endl;

    firstCpuData = firstCpuData.substr(5);
    std::string user = firstCpuData.substr(0,firstCpuData.find(" "));
    firstCpuData = firstCpuData.substr(user.size()+1);

    std::string nice = firstCpuData.substr(0,firstCpuData.find(" "));
    firstCpuData = firstCpuData.substr(nice.size()+1);

    std::string system = firstCpuData.substr(0,firstCpuData.find(" "));
    firstCpuData = firstCpuData.substr(system.size()+1);

    std::string idle = firstCpuData.substr(0,firstCpuData.find(" "));
    firstCpuData = firstCpuData.substr(idle.size()+1);

    info->User = user;
    info->System = system;
    info->Idle = idle;

    std::cout << "subfunction user:" << info->User << std::endl;
    std::cout << "subfunction system:" << info->System << std::endl;
    std::cout << "subfunction idle:" << info->Idle << std::endl;

    float total = std::stof(info->User) + std::stof(info->System) + std::stof(info->Idle);
    std::cout << "\ntotal  " << total << std::endl;
    std::cout << "user %   " << (std::stof(info->User) / total) * 100 << std::endl;
    std::cout << "system % " <<(std::stof(info->System) / total) * 100 << std::endl;
    std::cout << "idle %   " << (std::stof(info->Idle) / total) * 100 << std::endl;

    std::cout << "\nreturn \n\n";
    return 0;
} 

 ```
 　実行します。関数内で最新のCPUの時間データを取得し、構造体に書き込むと、mainに戻っても、更新された内容が生きていることがわかりました。
 　ここまで来ると、ポインタを使うと便利かもしれないと思いだします。
  でも、mainではメンバへの代入はドットを使い、ポインタを扱うときは->で代入をするというのが最後までエラーで残ったので、実際のプログラムを書くとき、ワケワカな状態になるのが見えるぞー
 ```
$ g++ works4p.cpp -o auto
$ ./auto

 in subroutine getCpuInfoData
cpu  70806 2961 47033 92421931 10975 0 33 0 0 0
subfunction user:70806
subfunction system:47033
subfunction idle:92421931

total  9.25398e+07
user %   0.0765141
system % 0.0508246
idle %   99.8727

return

main user:70806
main system:47033
main idle:92421931
```
　それにしても、CPUの処理時間のほぼ全部はidleなんですね。つまり、世界のコンピュータはほとんど休憩中だと。
 　なお、CPUの情報の１行目を取得し、最初に5文字を捨てていますが、user時間が増えると、4文字でよくなるかもしれません（プログラムが正常な結果を返さなくなる可能性あり）。なぜか、C++にsplitという関数がないんですね。自分で作る技量はありません。

 ！！！　この書き方を構造体を関数に参照渡しするっていう説明を複数見るが。ここで出てきた＆はアドレスを表すために使われている記号。次回は、参照のために使われる記号になる。。。

 ------

 https://qiita.com/jamjam/items/d9dfb1819b8ca513ac03

https://qiita.com/jamjam/items/cca4f181397daeac1ac2

https://qiita.com/jamjam/items/e7a734f85f4554ba6273

https://qiita.com/jamjam/items/28cb7fcd678b39378090  
  
https://qiita.com/jamjam/items/6c0b48747fd405989917