C言語　main(int argc, char const *argv[])について

## main関数

プログラムの指示された開始点。

main関数は以下のように定義される。

```c
int main (void) { body }

int main (int argc, char *argv[]) { body }
```

`int argc, char *argv[]`の部分はコマンドライン引数という。

`*argv[]`は`**argv`とも表現できる。ダブルポインタ。

参考: [main 関数 - cppreference.com](https://ja.cppreference.com/w/c/language/main_function)

## コマンドライン引数とは

>コマンドライン引数とは、コンピュータのコマンド入力画面（コマンドライン）からプログラムを起動する際に指定する文字列のこと。また、これをプログラム側で受け取った変数などの値。

参考: [コマンドライン引数とは - IT用語辞典 e-Words](http://e-words.jp/w/%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%83%A9%E3%82%A4%E3%83%B3%E5%BC%95%E6%95%B0.html)

main関数の引数はコマンドイラン引数と言われます。
コマンドライン引数は、プログラム実行時にOSに環境変数とともに指定するパラメータの1つです。

```c
int main(int argc, char const *argv[])
```

の `argc`, `argv`がコマンドライン引数。実行コマンドを取得する。

```terminal
$ ./a.out 100 abc
```
を実行すると中身は以下のようになる。

```terminal
argc=3; // コマンドライン引数の数
argv[0]="./a.out";
argv[1]="100";
argv[2]="abc";
```
- argv[0]には必ずパスを含めたファイル名が入る。
    - 厳密に言うと、`argv[0] がヌルでない場合、または argc > 0 である場合 (両者は同等です)、 argv[0] はプログラムの名前を表す文字列を指します。`
- 文字列として格納される。

がポイント

参考: [コマンドライン引数](http://www.ritsumei.ac.jp/~mmr14135/johoWeb/cmnds.html)
参考: [Argument definition by The Linux Information Project (LINFO)](http://www.linfo.org/argument.html)

<!--
## 標準入力とは

>標準入力とは、コンピュータ上で実行されているプログラムが、特に何も指定されていない場合に標準的に利用するデータ入力元。

参考: [標準入力とは - IT用語辞典 e-Words](http://e-words.jp/w/%E6%A8%99%E6%BA%96%E5%85%A5%E5%8A%9B.html)


> Standard input is by default any text entered from the keyboard. It is the counterpart of standard output and standard error, which are by default the display monitor.

参考: [What is standard input? -- a definition by The Linux Information Project (LINFO)](http://www.linfo.org/standard_input.html)

標準入力は、特に何も指定されていない場合に標準的に利用するデータ入力元として、キーボードから入力されるテキストを使います。

おすすめ
[標準入力・標準出力ってなに? - Qiita](https://qiita.com/angel_p_57/items/03582181e9f7a69f8168)

シェルがプログラム実行時に、この標準入力によって、入力された文字列をコマンドライン引数として使います。
-->
## argc、argvとは

- argc
  - "argument count"(引数の個数)の略
- argv
  - "argument vector"(引数の配列)の略

引数文字列の"配列へのポインタ"のことを指している。
あくまで、初めに用意されている言葉なので、他の関数同様に型さえ一緒であれば、int main(int a, char const *b[])や、int main(int a, char const **b)でも有効。

参考: [argc,argvとは？ - Qiita](https://qiita.com/hikarabitagobou/items/39c0e636455783a2463c)

## いつも打っているコマンドってプログラムにコマンドライン引数を渡して実行しているってことか！

これで理解できました。コマンドって実行ファイルに引数を渡したりして、実行させている。

```c
mkdir -p tests/test{1..5} && touch test/test1/file{3..5}.txt
```

とかも、実行ファイルに、コマンドイラン引数を使ってやり取りしているだけだった。コマンドは自分でも作れるということ。

参考: [C言語-コマンドの作成-コマンドラインとオプションの取得](http://masudahp.web.fc2.com/cl/tool/tool01.html)

コードランナーとか使って自動的にcompile、実行とかしていて、この辺理解しないで進めていたので、ハッとしました。

## おまけ1

```c
#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
    printf("argv[0]: %s\n", argv[0]);
    printf("sizeof(argv[0]): %zu\n", sizeof(argv[0]));
    printf("strlen(argv[0]): %zu\n", strlen(argv[0]));

    return 0;
}
```

実行結果

```terminal
./filepath/filename
sizeof(argv[0]): 8
strlen(argv[0]): 46
```

- argv[n]は文字列ではなく、文字列を示すポインタを格納している
  - char str[] = "filename";のstrではなく、&strであるということ
  - ポインタであるため、sizeof(argv)は8byteになる。
- strlenは指定されたアドレスからヌル終端文字までを取る。sizeof演算子との違いが改めて理解できた。

## おまけ2

環境変数が第３引数として渡される環境もある。その場合、以下のコードで参照することができる。

```c
#include <stdio.h>

int main(int argc, char** argv, char** envp)
{
    for(int i = 0; envp[i]; i++)
        puts(envp[i]);
}
```