C初学者にポインタとは何なのかを一言で説明

ポインタとは配列です。

まぁ別物ですけども…(小声)

とりあえずこちらをご覧ください。

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int i = 0;
    char arr[16] = { 0 };
    printf("arr's address : 0x%p\n", arr);

    for (i = 0; i < 16; i++)
    {
        arr[i] = i + 1;
    }

    return 0;
}

実行すると「arr's address : 0x0034FBB8」とコンソールに表示されましたので、for文前でbreakしてメモリを表示。

f:id:tydk27:20151209215846j:plain

ちゃんと16バイト分、0で初期化されてます。っで、配列なのでそれぞれの要素に値を入れていきます、というのがfor文以降。

f:id:tydk27:20151209215946j:plain

うんうん、ちゃんと1から16まで順に値が入っているもよう。ちなみに、0x0034FBD0の値はiのこと。

上のコードを下のように書き換えてみる。わかりやすくするため、char型のポインタで宣言して処理するバージョン。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    int i = 0;
    char *ptr;
    ptr = (char*)malloc(16);
    memset(ptr, 0x00, 16);

    printf("ptr's address : 0x%p\n", ptr);

    for (i = 0; i < 16; i++)
    {
        memset(&ptr[i], i + 1, 1);
    }
    free(ptr);

    return 0;
}

結果はアドレスが違うだけで全く同じなので省略。&ptr[i]、ってのがみそ、見慣れた(見飽きた?)配列的な書き方でつね。ポインタは配列、という証拠です(いみわからん)。下のようにptrをインクリメントしていく方法もある、けど

    for (i = 0; i < 16; i++, ptr++)
    {
        memset(ptr, i + 1, 1);
    }

と書いて、直後にfreeで解放しようとすると怒られます。そりゃそうだ、ポインタをインクリメントしちゃってるのだもの。freeで解放するときはmallocで確保した先頭アドレスと一緒じゃないとダメ。いちいちmallocした先頭アドレスまで戻すのもアレだし…ということです。

配列ってのは先頭アドレス固定なので、そういう意味でポインタと配列は全く別物。でも、上にあるような簡単なプログラムなら両者はほぼ一緒と考えていいと思う、カーネルソースを読んでいるわけじゃないんだし。

まとめると、

・ポインタは配列(のようなもの)
・ポインタのインクリメントはダメゼッタイ(ただしC初学者に限る)
・10 = 16

ポインタはもっと便利で素敵で意味不明で楽しいので、こんなところでねっとさーふぃんせずにコード書こう。と、自分に言い聞かせながら。こちらからは以上です。