ソフトウェア

C言語のポインタとは


前回記事の流れでC言語のポインタについて書かせていただきます。

今回の記事の内容はこれからIT業界を目指す人向けの内容からは少し脱線した内容となります。

しかしながら、機会の兼ね合いで、今回、敢えて書かせていただきますことご了承ください。

C言語のポインタを意識するのはプログラミングの仕事を初めてから2から3ヶ月後ぐらいの仕事内容がきっかけからくるのではとイメージしています。

このため、その2から3ヶ月後ぐらいの時期にこの記事を改めて読んでもらえるとうれしいです。

あわせてC言語自体これからという方が多いかと思いますので斜め読みだけで十分です。

それでは参りましょう。

本記事ではここでは敢えてC言語の文法など基礎部分については書きません。

C言語は書籍による学習と実践(仕事)で身につけることがベストとのスタンスであるため、
代わりに私がC言語を学ぶ上で役にたった本(今でも大切に保持している本)をご紹介いたします。

①「はじめてのC(改訂第4版[ANSI C対応])」(技術評論社)

②「ビジュアルラーニング C++入門」(X-media)


「C言語ポインタが理解できない理由」(技術評論社)

④「図解雑学 CPUの働きと高速化のしくみ」(ナツメ社)


その他、独習シリーズ(翔泳社)などありますが、本のページ数に圧倒されがちなの方が多いと思います。

まずは、上の4つをお勧めします。

特に③④①②の順番でお勧めです。
④ですが、プログラミング作業と実際の製品が動作するまでの一連の全体像を俯瞰でき、とても名著だと思っています。

では、本題です。

よくC言語で挫折する方は、ポインタでつまづく人が一番多いという迷信があるくらい障壁扱いされているようです(事実、私もそうでした、しかし③の本を読んでからは一変しました)。

では早速、C言語のポインタについて手短にポイントのみ、書かせていただきます。

①C言語ポインタを理解するために押さえておきたいツボの一覧

【ツボその1】

ポインタ型変数の中身=先頭1バイト目のアドレス番地
(ポインタのサイズは常に1バイトしかない)

メモリのアドレス番地とはメモリ上の住所(**県**市**町***番地のような)のことです。
しかしメモリのアドレス番地の値は"0x03fdab21"のような形で16進数で表現されます。しかし、この数字自体は覚える必要がありません、というか意味がありません。
(例)char *a → 変数aにはメモリアドレスの住所が格納される。

【ツボその2】

ポインタ型変数の左に*を付けた時の中身=メモリのアドレス番地に立っている建築物の名前
(例)char *a → 変数*aにはメモリアドレス番地に立っている建築物の名前が格納される。

【ツボその3】

ポインタを1つずらすということ=メモリのアドレス番地を変数型のサイズバイト分ずらすということ
(例)char型ポインタの場合
char* aのaに"0x03fdab21"という住所が入っていた場合に、
aを1つ前にずらす(a++;)とchar型のサイズ1byte分、住所がずれ、住所は"0x03fdab22"となる。
(例)int型ポインタの場合
int* bのbに"0x03fdab21"という住所が入っていた場合に、
bを1つ前にずらす(b++;)とint型のサイズ4byte分、住所がずれ、住所は"0x03fdab25"となる。

【ツボその4】

上の考え方はその他のポインタ(構造体型変数ポインタや関数ポインタ(C言語の中でも高等技術に相当します))でも同じです(=ポインタのサイズは常に1バイトしかない)。
(例)構造体型変数ポインタの例

typedef struct *kouzoutaipointer{
  char b;
  int c;
  double d;
}

kouzoutaipointer* a = malloc(kouzoutaipointer構造体のバイトサイズ)の時、
aには先頭1バイト目のメモリアドレス番地(char bの住所)が入っている。
構造体の値はa->b等で参照または変更できる。

【ツボ補足】

ダブルポインタ
あまり使われません(個人的には使用するとプログラミングコードの可読性が失われがちになる状況を見てきましたので、推奨しません。)
char **a →いわゆるポインタのポインタ(アドレスのアドレス)というものです。
実際の利用例で理解したほうがわかりやすいでしょう。
(例)
関数内で引数のアドレスを更新したい(例えば関数内でメモリ領域確保し、その先頭のアドレスを再設定したい)場合等

      void doublepointerfunc( char** a ){
        ...
         *a = &GLOBAL_HENSUU;(または*a = malloc(sizeof(4));)
        ...
      }

呼び出し側では
char **b = null;
*b = &a;
このタイミングで*bにはaのメモリアドレス番地が入っている。
doublepointerfunc(b);
このタイミングで*bにはGLOBAL_HENSUU(またはmalloc(sizeof(4))で確保したメモリの先頭)のメモリアドレス番地に置き換わっている。

いかかでしたでしょうか。

これからC言語を学ぼうという方にとっては、ちんぷんかんぷんな内容だったかもしれません。
許してください。

数か月後、改めてこの記事を思い出して頂ければ、少し救われます。。。

ただ、これからC言語を学ぼうという方にとっても、少しは参考になりそうな点があったかもしれないと思っています。

例えば"メモリ"、"16進数表記"等、これらはC言語の知識というよりもIT全般に共通する知識です。
このため、C言語の書籍学習(冒頭で紹介した本等を利用した学習)と並行してIT全般に共通する知識の学習も同時並行で進めていけるとベストだと思います。

この知識は我流で身につけることは不可能ではなくても非常に効率が悪くなります。
そのため、独学でもこれからIT業界で食べていくために必要なデファクトスタンダードな知識を系統的に身につけられるツールを積極的に利用していきましょう。

なお、そのツールは「基本情報技術者試験」と呼ばれています。
アラサー未経験からIT業界に飛び込む場合、まずこの資格を取れるレベルを目指しましょう。
(基本といっても簡単ではありません。数字のセンスも必要です。おそらくかなり難しく感じるでしょう)。

今回はプログを始めたばかりにも関わらず、話がかなり脱線してしまいました。

次回は少し、レールを戻す形で、これからという方のために「基本情報技術者試験」の内容についてご紹介いたします。

-ソフトウェア