C言語入門|argvと二重ポインタのしくみ

ここまでで、コマンドライン引数を使って
main関数に文字列を渡せることは理解できましたね。

でも、最後に1つだけ、どうしても避けて通れない壁があります。

「char** argv って、結局なんなんですか?」

そう、二重ポインタ(ダブルポインタ) です。

名前からして強そうですが、
実は argv は「二重ポインタ入門」にちょうどいい題材なんです。

まずは argc を確認してみよう

最初に確認しやすいのは argc です。

argc には
プログラム名 + コマンドライン引数の個数
が入ります。

サンプルプログラム

プロジェクト名:11-13-1 ソースファイル名: sample11-13.1.c

#include <stdio.h>

int main(int argc, char** argv)
{
    printf("argc=%d\n", argc);
    return 0;
}

実行結果(引数なし)

argc=1

これは、
プログラム名だけが渡されている状態 です。

Visual Studioでコマンドライン引数を指定する

Visual Studioでは、次の手順で引数を指定します。

  1. メニューから
    プロジェクト → プロパティ を選択
  2. 左側で
    構成プロパティ → デバッグ を選択
  3. 「コマンド引数」の欄に次を入力
    hello C
  4. デバッグ → デバッグの開始 を選択

実行結果

argc=3

プログラム名 + hello + C
で、合計3つですね。

argv が本体、argc は補助

argc で「数」はわかりました。
では、実際の中身 はどこにあるのでしょう?

それが argv です。

argv には、
渡されたすべての文字列の情報
が入っています。

argv の正体をイメージで理解する

argv は char** 型です。

これは、

  • char* 型の情報が
  • 配列のように並んでいる
  • その先頭アドレスを指している

という意味です。

つまり、

argv → [ char* ][ char* ][ char* ] ...

という構造になっています。

なぜ char** になるのか

ここで、型の考え方を整理しましょう。

指しているもの
文字char
文字列の先頭アドレスchar*
文字列の先頭アドレスが並ぶ領域char**

「アドレスの指す先に char* 型の値がある」

だから argv は char 型になる、というわけです。

argv[i] は何を意味しているのか

argv は配列のように使えます。

argv[0]
argv[1]
argv[2]
[] 演算子で取り出したものは、
すべて char 型* です。

つまり、

  • argv[0] → プログラム名の文字列
  • argv[1] → 1番目の引数
  • argv[2] → 2番目の引数

になります。

argv の中身を確認してみよう

サンプルプログラム

プロジェクト名:11-13-1 ソースファイル名: sample11-13-1.c

#include <stdio.h>

int main(int argc, char** argv)
{
    printf("argc=%d\n", argc);

    for (int i = 0; i < argc; i++) {
        char* strAddr = argv[i];
        printf("%d番目の引数:%s\n", i, strAddr);
    }
    return 0;
}

引数を指定せずに実行

argc=1
0番目の引数:C:\Users\...\Debug\sample11-13-1.exe

引数を指定して実行してみる

Visual Studio の
「コマンド引数」に次を入力します。

hello C world

実行結果

argc=4
0番目の引数:C:\Users\...\Debug\sample.exe
1番目の引数:hello
2番目の引数:C
3番目の引数:world

argv には、
文字列の先頭アドレスが順番に並んでいる
ことが、はっきり確認できますね。

二重ポインタは怖くない

二重ポインタと聞くと身構えてしまいがちですが、
本質はとてもシンプルです。

  • Y* 型の値が
  • 配列のように並んでいる
  • その先頭アドレスを扱う

このとき、型は Y になります。

argv は二重ポインタの代表例

argv は、

  • 文字列の配列
  • 2次元配列の考え方
  • ポインタの段階構造

これらを一度に学べる、
二重ポインタの王道サンプル です。

ここを理解できれば、

  • char**
  • int**
  • 構造体**

といった型にも、冷静に向き合えるようになります。

二重ポインタで慌てないために

X* 型を見たら、こう考えてください。

「X 型の情報が、配列のように並んでいる領域の先頭アドレスだ」

紙に図を書き、
1段ずつ「何を指しているか」を追っていけば、
必ず理解できます。

ここまで来たあなたは、
もう ポインタを感覚ではなく構造で理解できる C言語エンジニアです。

次に三重ポインタが出てきても、
きっと落ち着いて対処できますよ。