びっと飯店

材料は0と1

#1 はじめてのポインタ

テキトーにブログのネタ募集したら「ポインタ」というお題が来たのでこれについて書こう.その前に,「アドレス」について理解が必要なのでこちらから書いていこう.ちなみに,C言語を前提として書いていくのでそこだけご注意を!

アドレスとは

メモリアドレス(英: memory address)は、コンピュータの主記憶装置にアクセスするためにソフトウェアおよびハードウェアによって様々なレベルで使用されるデータ概念である。通常、メモリアドレスは、符号なし(英語版)整数として表示・処理される固定長の数字の列である[1]。

超簡単に言うと「メモリ上の場所を表すもの」だ.
メモリは1バイトごとに「アドレス」が割り振られており,アドレスを指定することで,そこに書かれている情報を読み込むことができる.

ちなみに,&をつけるとアドレスを表し,printf("%p\n", &n);と書くと,変数nのアドレスを表示することができる.

ポインタとは

ポインタ (pointer) とは、あるオブジェクトがなんらかの論理的位置情報でアクセスできるとき、それを参照する(指し示す)ものである。有名な例としてはC/C++でのメモリアドレスを表すポインタが挙げられる。 Wikipediaより

ポインタは,とある変数のアドレスを格納しており,以下の場合ではポインタ変数pはint型変数nのアドレスである0x80568144が格納されている.

f:id:futamu:20190725220758p:plain:w600

豆知識

データ型によって必要とするメモリ領域が異なる.例えばint型の場合は4バイト,double型なら8バイト必要とする.

さらに,ポインタ変数にはアドレスが格納されていると言ったが,アドレスは32ビット,つまり4バイトでありポインタ変数は4バイト必要とする.したがって,どのデータ型を指してもこれは変わらず4バイト必要とするのだ.

ちなみに,以下の図のようにポインタ変数はその開始アドレスを格納している.

f:id:futamu:20190725224653p:plain:w600

ポインタの使い方

ポインタ演算子である*を用いて以下のように書くことができる.

型名 *ポインタ名;
型名* ポインタ名;
型名 * ポインタ名;

「JIS X 3010」という規格書の中では1つ目の書き方が用いられているが,どう書いても動くためそこまで強く意識する必要はないと思われる.

ちなみに

int *p, n;

と書くと,pだけがint型のポインタとして扱われるので注意が必要だ.

変数nにポインタを介して値を代入してみよう.

#include <stdio.h>

int main(void){
  int n;    // int型変数nを定義
  int *p;   // int型ポインタ変数pを定義
  
  p=&n;     // nのアドレスをpに代入
  *p=346;   // *pが指す位置(nのアドレス)に346を代入
  
  return 0;
}

上のように書くと,ポインタを介して値が代入される.

ポインタのポインタ

ポインタ変数自体もアドレスは割り振られているので,そのアドレスをさらに別のポインタ変数に格納することもできる,というのはなんとなく想像がつくんじゃなかろうか?

型名 **ポインタ名;

上のように書くとそれを実現できる.

f:id:futamu:20190726135057p:plain:w600

#include <stdio.h>

int main(void){
  int n;      // int型変数nを定義
  int *p;     // int型ポインタ変数pを定義
  int **pp;   // int型ポインタのポインタ変数ppを定義
  
  p=&n;       // nのアドレスをpに代入
  pp=&p;      // pのアドレスをppに代入
  **pp=346;   // **ppが指す位置(nのアドレス)に346を代入
  
  return 0;
}

上のように書くと,ポインタのポインタを介して値が代入される.