結論
main の引数は自分で渡すのではなく、プログラム起動時にOSが用意して渡す
main関数の定義
int main(int argc, char *argv[])
• argc:引数の個数
• argv:引数の配列(正確にはポインタ配列)
引数はどこで渡すのか
ターミナルで実行するときに渡す。
./a.out hello world
このときOSが内部で次のようなデータを作る:
argc = 3;
argv = ["./a.out", "hello", "world"];
メモリ上の構造
① 文字列が配置される
"./a.out\0"
"hello\0"
"world\0"
各文字列は \0(終端文字)付きの配列としてメモリに置かれる。
② ポインタ配列(argv)が作られる
argv
├─ [0] → "./a.out"
├─ [1] → "hello"
├─ [2] → "world"
└─ [3] → NULL
argv は「文字列そのもの」ではなく、文字列へのアドレスを並べた配列。
③ mainに渡される
argc = 3;
argv = 配列の先頭アドレス
argvの正体
char *argv[]
これは次と同じ意味:
char **argv
つまり:
• argv は「ポインタのポインタ」
• 「文字列の先頭アドレス」を指すポインタの配列
アクセスの仕組み
argv[1]
は内部的に:
*(argv + 1)
さらに:
argv[1][0]
は:
((argv + 1) + 0)
なぜ & をつけないのか
• argv はすでに「アドレス(ポインタ)」として渡されている
• OSが用意したデータを受け取っているだけ
そのため、自分で & をつけて渡す場面はない
まとめ
• main は自分で呼び出さない(OSが呼ぶ)
• 引数は「実行時にターミナルから渡す」
• argv は「文字列の配列」ではなく「文字列のアドレスの配列」
• & は不要(すでにポインタだから)
補足
例:
./a.out hello world
argv[0] = "./a.out"
argv[1] = "hello"
argv[2] = "world"