おさえておきたいプログラミングの基本
普通の変数にポインタ変数があるように、実はポインタ変数にも、ポインタがあります。まずは、以下のサンプルを実行してみてください。
listex3-fp-1:main.c#include <stdio.h>
int main(int argc,char** argv){
char *s[3] = { "Taro","Hanako","Tom" };
char **pps = NULL; // ポインタのポインタ
int i;
for(i = 0; i < 3; i++){
printf("%s\n",s[i]);
}
pps = s;
for(i = 0; i < 3; i++){
printf("%s\n",*pps);
pps++; // アドレスを一つずらす
}
return 0;
}
実行結果
4行目を実行することにより、s[0]には"Taro"、s[1]には"Hanako"、s[2]には"Tom"という値が入った文字列の変数(二次元配列)が出来上がります。7から8行目で、それらを表示しています。
5行目で定義されているのが、ポインタのポインタです。ポインタのポインタは、変数の型の跡に**をつけます。
10行目で、ppsに、sを代入しています。変数sは、それぞれの文字列の先頭アドレスのポインタの配列となっていることから、これによりs[0]のアドレスを取得していることになります。
型の定義の仕方こそ特殊ですが、関数ポインタも、ポインタ変数の一種です。ただ、そこに代入するのはあくまでも関数です。
続いて、関数の引数としてポインタのポインタを利用するケースを見て見ましょう。以下のサンプルを実行してみてください。
listex3-fp-2:main.c#include <stdio.h>
#include <string.h>
#include <malloc.h>
int createMemory(char**,int);
void freeMemory(char**);
int main(int argc,char** argv){
char* s = NULL;
createMemory(&s,255);
strcpy(s,"HelloWorld\n");
printf("%s",s);
freeMemory(&s);
return 0;
}
// メモリの確保
int createMemory(char** mem,int size){
if(*mem == NULL){
*mem = (char*)malloc(sizeof(char) * size);
// メモリが生成できなければエラー
if(*mem == 0){
return -1;
}
return 0;
}
// 与えられたメモリの値が不定ならば、エラー
return -1;
}
// メモリの開放
void freeMemory(char** mem){
if(mem != 0){
free(*mem);
}
}
実行結果
createMemory、および、freeMemoryという関数で、引数としてポインタのポインタが利用されていています。このサンプルのように、メモリの生成や消去を関数内で行いたい場合は、ポインタではなく、ポインタのポインタを渡すことになります。
この方法の利点は、ポインタの状態のチェックなどといったコードを関数内でできることから、ソースコードの中に同じようなコードを何度も記述する必要がないという点です。
練習問題 : 問題3.
一週間でわかるC言語・C++言語がオンライン講座になりました!動画と音声によってさらにわかりやすくなりました!! 1講座で2つの言語を学ぶことができる上に、練習問題の回答もダウンロードできます。
Read →本講座が「1週間でC言語の基礎が学べる本」として書籍化されました!サイトの内容プラスアルファでより学習しやすくなっています!Impressより発売中です!!
Read →