https://youtu.be/49gLUpHMKdY
\textcolor{pink}{四国めたん: } 教師役ですわ
\textcolor{lime}{ずんだもん: } 生徒役なのだ
\footnotesize \textcolor{pink}{四国めたん:} 皆さん、こんにちは。四国めたんです
\footnotesize \textcolor{lime}{ずんだもん:} ずんだもんなのだ。こんにちはなのだ
\footnotesize \textcolor{pink}{四国めたん:} 今回もC言語のお勉強をしていきましょう
\footnotesize \textcolor{lime}{ずんだもん:} レッツゴーなのだ
\footnotesize \textcolor{pink}{四国めたん:} ずんだもんさん、C言語は基本的には 高級言語 だということはお分かりですわね
\footnotesize \textcolor{lime}{ずんだもん:} とうぜんなのだ
\footnotesize \textcolor{lime}{ずんだもん:} 英文に近い言葉を使ってプログラミングができる、すぐれものなのだ
\footnotesize \textcolor{pink}{四国めたん:} そうですわね
\footnotesize \textcolor{pink}{四国めたん:} いっぽうで、C言語は 高級アセンブラ と揶揄されることもありますわ
\footnotesize \textcolor{lime}{ずんだもん:} アセンブラ ?
\footnotesize \textcolor{pink}{四国めたん:} コンピュータが直接理解できる言葉は 機械語 と呼ばれていますわ
\footnotesize \textcolor{pink}{四国めたん:} そして、 アセンブラ は 機械語 に非常に近い言語のことですわ
\footnotesize \textcolor{lime}{ずんだもん:} どうしてC言語は 高級アセンブラ と揶揄されるのだ?
\footnotesize \textcolor{pink}{四国めたん:} 実は、C言語は 高級言語 であるにも関わらず アセンブラ に近いことができるのですわ
\footnotesize \textcolor{lime}{ずんだもん:} なるほど、 アセンブラ と同じことができる 高級言語 ということか…
\footnotesize \textcolor{pink}{四国めたん:} そうですわね
\footnotesize \textcolor{pink}{四国めたん:} そして、それが今でもC言語の人気が落ちない理由のひとつでもありますわ
\footnotesize \textcolor{lime}{ずんだもん:} ところで、C言語のどのあたりが アセンブラ に似ているのだ
\footnotesize \textcolor{pink}{四国めたん:} それこそが今回お話しする ポインタ ですわ
\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ
\footnotesize \textcolor{pink}{四国めたん:} まずは ポインタ の前に、密接に係る メモリ のアドレスについて説明していきますわね
\footnotesize \textcolor{lime}{ずんだもん:} よろしくなのだ
メモリの知識は必須です
\footnotesize \textcolor{pink}{四国めたん:} メモリ は読んで字のごとくデータを一時的に記憶(Memory)する場所ですわ
\footnotesize \textcolor{lime}{ずんだもん:} どのようなデータを記憶しておくのだ?
\footnotesize \textcolor{pink}{四国めたん:} プログラムで使用する変数は、基本的に全てメモリで記憶しますわね
\footnotesize \textcolor{lime}{ずんだもん:} いまひとつイメージがわかないのだ
\footnotesize \textcolor{pink}{四国めたん:} 以前にもお話ししましたが、イメージとしてはメモ帳がメモリに相当していますわ
\footnotesize \textcolor{pink}{四国めたん:} そして変数の宣言は、メモ帳に変数名を書いた付箋を貼るような感じですわ
\footnotesize \textcolor{lime}{ずんだもん:} う~ん…
\footnotesize \textcolor{pink}{四国めたん:} さらに、付箋の色が変数の型に相当すると考えると判り易いかと思いますわ
\footnotesize \textcolor{lime}{ずんだもん:} なんとなくイメージが湧いてきたのだ
\footnotesize \textcolor{pink}{四国めたん:} 変数の初期化は、付箋を付けたメモ帳のページに値を記入する事と考えられますわ
\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ
\footnotesize \textcolor{lime}{ずんだもん:} 変数へのデータの代入は、どんなイメージなのだ?
\footnotesize \textcolor{pink}{四国めたん:} 既に値が書き込まれているページの場合には、前の値を二重線で消すか消しゴムで消すかして新たな値を記入しますわ
\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ
メモリには単位があります
\footnotesize \textcolor{pink}{四国めたん:} まずは メモリ の単位についてお話ししますわ
\footnotesize \textcolor{lime}{ずんだもん:} 単位というと、長さのメートルや重さのグラムとかのことか?
\footnotesize \textcolor{pink}{四国めたん:} はい、メモリの基本となる単位は バイト ですわ
\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ
\footnotesize \textcolor{lime}{ずんだもん:} ということは、長さや重さと同じく、1000バイトで1キロバイトということか?
\footnotesize \textcolor{pink}{四国めたん:} おしいですわね
\footnotesize \textcolor{pink}{四国めたん:} 実は メモリ では1024バイトが1キロバイトに、1024キロバイトが1メガバイトになりますわ
\footnotesize \textcolor{lime}{ずんだもん:} 1000ではなく、1024毎なのか…
\footnotesize \textcolor{pink}{四国めたん:} はい、プログラミングの世界では、1000ではなく1024毎にキロ(k)、メガ(M)、ギガ(G)、テラ(T)…となっていくのですわ
\footnotesize \textcolor{lime}{ずんだもん:} りょうかいなのだ
\footnotesize \textcolor{pink}{四国めたん:} そして先ほどのメモ帳を例にとると、1ページがメモリの1バイトに相当しますわ
\footnotesize \textcolor{lime}{ずんだもん:} その1バイトのメモリには、どのようなデータを記憶できるのだ?
\footnotesize \textcolor{pink}{四国めたん:} 1バイトのメモリ、つまり、メモ帳の1ページには2桁の16進数 のみ書き込むことができますわ
\footnotesize \textcolor{lime}{ずんだもん:} 2桁の16進数?
\footnotesize \textcolor{pink}{四国めたん:} はい、0x00(0)から0xFF(255)までの数値のみですわ
\footnotesize \textcolor{pink}{四国めたん:} もしくは0x80(-128)~0xFF(-1)、0x00(0)~0x7F(127)のように負数を含めた数値の場合もありますわ
\footnotesize \textcolor{lime}{ずんだもん:} 数値の先頭に付いている"0x"はなんなのだ?
\footnotesize \textcolor{pink}{四国めたん:} 数値の先頭に付いている"0x"は16進数を表す接頭辞ですわ
\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ
\footnotesize \textcolor{pink}{四国めたん:} ところで0~127って何処かで見たような気がしませんか?
\footnotesize \textcolor{lime}{ずんだもん:} ASCIIコード?
\footnotesize \textcolor{pink}{四国めたん:} その通りですわ
\footnotesize \textcolor{pink}{四国めたん:} つまり、1バイト(メモ帳の1ページ)は char型 の変数に相当しますわね
\footnotesize \textcolor{lime}{ずんだもん:} int型 や double型 は何バイトのメモリを使うのだ?
\footnotesize \textcolor{pink}{四国めたん:} int型 は4バイト、 double型 は8バイトの変数となりますわ
\footnotesize \textcolor{lime}{ずんだもん:} 整数や浮動小数点数は、結構、多くのメモリを使うのだ
メモリにはアドレスが割り振られます
\footnotesize \textcolor{pink}{四国めたん:} さて変数がメモリに割り当てられることは、お話ししましたわね
\footnotesize \textcolor{lime}{ずんだもん:} おぼえているのだ
\footnotesize \textcolor{lime}{ずんだもん:} でも、どのように割り当てられるのかはわからないのだ
\footnotesize \textcolor{pink}{四国めたん:} 通常はメモリの各バイトに対して連続した番号が割り振られますわ
\footnotesize \textcolor{pink}{四国めたん:} これらの番号は一般的には メモリのアドレス と呼ばれますわね
\footnotesize \textcolor{lime}{ずんだもん:} イメージがわかないのだ
\footnotesize \textcolor{pink}{四国めたん:} メモ帳に例えれば、各ページのページ番号が アドレス に相当しますわ
\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ
\footnotesize \textcolor{pink}{四国めたん:} メモリに対してコンピューターは基本的には自動で変数を割り当てますわ
\footnotesize \textcolor{pink}{四国めたん:} ですので最初の内は変数に割り当てられたメモリのアドレスを気にする必要はありませんわ
\footnotesize \textcolor{lime}{ずんだもん:} 最初のうちは?
\footnotesize \textcolor{pink}{四国めたん:} はい、ハードウェアの制御を行うプログラムを作るようになれば、嫌でもアドレスを気にするようになりますわ
\footnotesize \textcolor{lime}{ずんだもん:} はやくそうなりたいのだ
\footnotesize \textcolor{pink}{四国めたん:} メモリについての簡単な説明は以上ですわ
バイトよりも小さい単位
実は バイト よりも小さい ビット というメモリの単位があります
1ビットは0か1、もしくはONとOFFしか表現できません
いわばスイッチのような機能を持っています
というか、メモリは実際に数百億個の半導体のスイッチが並んでいるんですけど…
そして8ビットが1バイトに相当します
結果として1バイトで2の8乗の値、0~255の整数値を表現できるようになります
ただ、メモリのアドレスは一般的にバイト単位で割り当てられます
また、コンピューターの処理も基本的にはバイト単位で行われます
ですので、ビット単位での処理や操作には、多少の工夫が必要になってきます
ポインタはC言語のキモです
\footnotesize \textcolor{pink}{四国めたん:} 続いて ポインタ についてお話ししていきますわ
\footnotesize \textcolor{lime}{ずんだもん:} よろしくなのだ
\footnotesize \textcolor{pink}{四国めたん:} 今まで変数については宣言を行って変数名を割り当てていましたわ
\footnotesize \textcolor{pink}{四国めたん:} そして変数名を使用してデータの代入や参照をおこなってきましたわ
\footnotesize \textcolor{lime}{ずんだもん:} おぼえているのだ
\footnotesize \textcolor{pink}{四国めたん:} ポインタ は変数名の代わりに、メモリのアドレスを指定してデータの代入や参照を行う機能のことですわ
\footnotesize \textcolor{lime}{ずんだもん:} イメージがわかないのだ
\footnotesize \textcolor{lime}{ずんだもん:} 変数が割り当てられたメモリのアドレスを、変数名の代わりに指定するということか?
\footnotesize \textcolor{pink}{四国めたん:} その通りですわ
\footnotesize \textcolor{lime}{ずんだもん:} それってメリットがあるのか?
\footnotesize \textcolor{lime}{ずんだもん:} 直接、変数名を指定した方が効率的ではないのか?
\footnotesize \textcolor{pink}{四国めたん:} まぁ、その疑問はもっともですわ
\footnotesize \textcolor{pink}{四国めたん:} 実際、 ポインタ はC言語の最大のメリットでありデメリットでもありますわ
ポインタ型の宣言と初期化をするよ
\footnotesize \textcolor{pink}{四国めたん:} ポインタは「アドレスを指定して」とは云うものの、そのアドレスを保持しておく場所が必要となりますわ
\footnotesize \textcolor{lime}{ずんだもん:} たしかに
\footnotesize \textcolor{pink}{四国めたん:} なので 変数のアドレス を保持する 変数 を用意する必要がありますわ
\footnotesize \textcolor{lime}{ずんだもん:} アドレスも変数に入れるのか?
\footnotesize \textcolor{pink}{四国めたん:} その通りですわ
\footnotesize \textcolor{lime}{ずんだもん:} ところで アドレス は、どのようにして得られるのだ?
\footnotesize \textcolor{pink}{四国めたん:} アドレス は自動で割り当てられますわ
\footnotesize \textcolor{lime}{ずんだもん:} どのようなアドレスになるかは判らないのか…
\footnotesize \textcolor{pink}{四国めたん:} アドレスの値は、当面は気にする必要はありませんわ
\footnotesize \textcolor{lime}{ずんだもん:} なんかモヤモヤするのだ
\footnotesize \textcolor{pink}{四国めたん:} そして、 アドレス を保持する変数の型は ポインタ型 と呼ばれますわ
\footnotesize \textcolor{lime}{ずんだもん:} ポインタ型 ?
\footnotesize \textcolor{pink}{四国めたん:} はい、もしくは int型のポインタ や float型のポインタ 等とも言うことがありますわ
\footnotesize \textcolor{lime}{ずんだもん:} int型 や float型 の変数のアドレスを保持する変数の型のことか?
\footnotesize \textcolor{pink}{四国めたん:} 鋭いですわね
\footnotesize \textcolor{lime}{ずんだもん:} ところで ポインタ型 の変数の宣言と初期化、代入は、どのように行えばいいのだ?
\footnotesize \textcolor{pink}{四国めたん:} まず、宣言は元の変数の型の後ろにアスタリスク*
を付けて行いますわ
\footnotesize \textcolor{lime}{ずんだもん:} 型* 変数名;
ということか?
\footnotesize \textcolor{pink}{四国めたん:} その通りですわ
\footnotesize \textcolor{pink}{四国めたん:} そして変数の初期化については、NULL
もしくは通常の型の変数のアドレスを代入しますわ
\footnotesize \textcolor{lime}{ずんだもん:} NULL
?
\footnotesize \textcolor{pink}{四国めたん:} はい、どのアドレスも指していないことを示す定数ですわ
\footnotesize \textcolor{lime}{ずんだもん:} 0ではダメなのか?
\footnotesize \textcolor{pink}{四国めたん:} 0でも問題ない場合は多いですが、できるだけNULL
を使って下さいね
\footnotesize \textcolor{lime}{ずんだもん:} わかったのだ
\footnotesize \textcolor{pink}{四国めたん:} また変数のアドレスは アドレス演算子 &
で取得できますわ
\footnotesize \textcolor{lime}{ずんだもん:} つまり、宣言と初期化は型* 変数名 = NULL;
や型* 変数名 = &変数;
で行えるのか
\footnotesize \textcolor{pink}{四国めたん:} その通りですわ
\footnotesize \textcolor{lime}{ずんだもん:} 具体的な例をおねがいするのだ
\footnotesize \textcolor{pink}{四国めたん:} わかりましたわ
#include <stdio.h>
void main() {
int x = 1;
int* py = NULL;
py = &x;
printf("xのアドレスは%pです\n", py);
}
\footnotesize \textcolor{lime}{ずんだもん:} 変数"x"のアドレスが表示されたのだ
\footnotesize \textcolor{pink}{四国めたん:} 表示されるアドレスについては異なっていると思いますが、気にしなくてもOKですわ
\footnotesize \textcolor{lime}{ずんだもん:} りょうかいなのだ
\footnotesize \textcolor{lime}{ずんだもん:} それよりもプログラムの説明をおねがいするのだ
\footnotesize \textcolor{pink}{四国めたん:} まずポインタ型の変数"py"の宣言と初期化をint* py = NULL;
でおこなっていますわ
\footnotesize \textcolor{lime}{ずんだもん:} int*
は int型 の変数のポインタということか
\footnotesize \textcolor{pink}{四国めたん:} その通りですわ
\footnotesize \textcolor{pink}{四国めたん:} ちなみにNULL
は"stdio.h"内で定義されていますわ
\footnotesize \textcolor{lime}{ずんだもん:} "stdio.h"は#include
ディレクティブで読み込んでいるのだ
\footnotesize \textcolor{pink}{四国めたん:} そして変数"x"に割り当てられたアドレスを&x
で取得して"py"に代入していますわ
\footnotesize \textcolor{lime}{ずんだもん:} int* py = &x;
でもいいのではないのか?
\footnotesize \textcolor{pink}{四国めたん:} その通りですけれど、NULL
による初期化の説明のために、今回は分けましたわ
\footnotesize \textcolor{lime}{ずんだもん:} 大人の事情なのだ
\footnotesize \textcolor{pink}{四国めたん:} 最後にprintf
で"py"に代入された変数"x"のアドレスを表示していますわ
\footnotesize \textcolor{lime}{ずんだもん:} "%p"はなんなのだ?
\footnotesize \textcolor{pink}{四国めたん:} アドレスを表示するための書式指定子ですわね
\footnotesize \textcolor{lime}{ずんだもん:} わかったのだ
NULL / 0 / nullptr / NUL
!
無効なポインタ を示すためにNULL
の代わりに0を使っているのを見かけますが厳密には間違いです
ヘッダー内では確かにNULL
を((void *)0)
と表現している場合が多いのですが、異なることもあるからです
0xFFFFFFFFや0xFFFFFFFEのように定義している場合もあります
これはCPUやOS、コンパイラ等によって決まります
ですので 無効なポインタ を示すためにはNULL
を使いましょう
C++や最新のC言語の規格ではNULL
の他にnullptr
がキーワードとして追加されています
動作的には変わらないのですが、バグの回避と云う点ではnullptr
の方が勝っています
使えるのであればNULL
よりもnullptr
を使いましょう
最後にNUL
ですがASCIIコード表の0x00に相当する値でchar
型です
意味としては NULL文字 となります
なおNULL
はポインタ型なので char型 のNUL
とは全く異なります
混同して使っている場合も見受けられますので注意が必要です
アスタリスクの位置
ポインタ型の宣言の際、アスタリスク"*"を元の変数の型の直後に置くか、ポインタの変数名の直前に置くかで意見が別れます
元の変数の型の直後: int* p;
ポインタの変数名の直前: int *p;
どちらも正しいのですが個人的には元の変数の型の直後に置く方式を推します
その場合には複数の変数の宣言を一度に行うのは、バグの元になりますので止めましょう
まぁ好みの領域なので統一していればOKです
ポインタを使ってアクセスします
\footnotesize \textcolor{lime}{ずんだもん:} ところでポインタを使って元の変数の値を参照したり変更したりするにはどうしたらいいのだ?
\footnotesize \textcolor{pink}{四国めたん:} ポインタが指し示すアドレスに割り当てられた変数にアクセスするためには、ポインタ型の変数に 間接演算子 *
を使いますわ
\footnotesize \textcolor{lime}{ずんだもん:} 間接演算子 ?
\footnotesize \textcolor{pink}{四国めたん:} はい、 間接参照演算子 ともいいますわね
\footnotesize \textcolor{lime}{ずんだもん:} 具体的に教えてほしいのだ
\footnotesize \textcolor{pink}{四国めたん:} それでは例を見てみましょう
#include <stdio.h>
void main() {
int x = 1;
int* py = &x;
*py = 2;
printf("xの値は%dです\n", x);
}
\footnotesize \textcolor{lime}{ずんだもん:} 「xの値は2です」と表示されたのだ
\footnotesize \textcolor{pink}{四国めたん:} とりあえずプログラムを解説して行きますわ
\footnotesize \textcolor{lime}{ずんだもん:} おねがいするのだ
\footnotesize \textcolor{pink}{四国めたん:} まず"py"は int型 の変数"x"のアドレスで初期化していますわ
\footnotesize \textcolor{pink}{四国めたん:} そして*py = 2;
では 間接演算子 *
により"py"の示すアドレスの変数、つまり"x"に2を代入していますわ
\footnotesize \textcolor{lime}{ずんだもん:} つまり ポインタ型 の変数の前にアスタリスク*
を付ければ、元の変数と同じように使えるのか…
\footnotesize \textcolor{pink}{四国めたん:} その通りですわ
\footnotesize \textcolor{lime}{ずんだもん:} でも ポインタ型 の変数の宣言のときもアスタリスク*
を使うので混乱してしまうのだ
\footnotesize \textcolor{pink}{四国めたん:} たしかにどちらもアスタリスク*
を使用するので少し混乱しますが、使用する場所が違いますので、しっかりと区別をつけて下さいね
\footnotesize \textcolor{lime}{ずんだもん:} がんばるのだ
\footnotesize \textcolor{lime}{ずんだもん:} そういえば掛け算の演算子もアスタリスク*
を使うが、間違えてしまわないのか?
\footnotesize \textcolor{pink}{四国めたん:} まぁ、掛け算の場合には、前後に数値や変数がありますから
\footnotesize \textcolor{lime}{ずんだもん:} たしかにポインタの演算子の場合には、前に数値や変数を置くことはできないのだ
\footnotesize \textcolor{pink}{四国めたん:} 見た目で判り易くする場合には、掛け算の場合には前後に空白を入れるようにすればいいですわ
\footnotesize \textcolor{pink}{四国めたん:} またポインタの演算子の場合には、変数との間を詰めればいいですわね
\footnotesize \textcolor{lime}{ずんだもん:} なるほど、判り易いのだ
1 * 2; // 掛け算は前後に数値や変数が必要
*a; // ポインタの演算子は前に数値や変数が無くてもいい
ポインタを関数に使いましょう
\footnotesize \textcolor{lime}{ずんだもん:} ところでポインタを使うメリットは何なのだ?
\footnotesize \textcolor{pink}{四国めたん:} たしかに、単にアドレスを通して変数にアクセスするだけではメリットはありませんわね
\footnotesize \textcolor{lime}{ずんだもん:} それだけなら変数に直接アクセスする方がはるかに効率的なのだ
\footnotesize \textcolor{pink}{四国めたん:} ひとつの大きなメリットを挙げるなら、関数の引数にポインタ型を使う場合ですわ
\footnotesize \textcolor{lime}{ずんだもん:} そうなのか?
\footnotesize \textcolor{pink}{四国めたん:} はい、以前にお話ししましたが、関数の引数はデータのコピーが使用されますわ
\footnotesize \textcolor{pink}{四国めたん:} ですので、関数内で引数の値を変更しても、呼び出し側の値が変わるわけではありませんわ
\footnotesize \textcolor{lime}{ずんだもん:} おぼえているのだ
\footnotesize \textcolor{pink}{四国めたん:} そこで関数の引数にポインタ型を使用するとどうなるでしょう?
\footnotesize \textcolor{lime}{ずんだもん:} 元の変数を指し示すアドレスがコピーされるのだ
\footnotesize \textcolor{pink}{四国めたん:} そして、そのポインタを通して元の変数にアクセスする事が可能となりますわ
\footnotesize \textcolor{lime}{ずんだもん:} つまり、ポインタを通して元の変数の値を変更すれば、関数内で呼び出し側の変数の値を変える事が可能となるのか
\footnotesize \textcolor{pink}{四国めたん:} その通りですわ
\footnotesize \textcolor{pink}{四国めたん:} 例として以前のプログラムのadd
関数について、引数にポインタ型を使ってみましょう
#include <stdio.h>
void add(int* pa, int b) {
*pa = *pa + b;
return;
}
void main() {
int x = 1;
int y = 2;
add(&x, y);
printf("xとyの和は%dです\n", x);
}
\footnotesize \textcolor{lime}{ずんだもん:} プログラムの説明をおねがいするのだ
\footnotesize \textcolor{pink}{四国めたん:} わかりましたわ
\footnotesize \textcolor{pink}{四国めたん:} まず、関数add
の第1引数はポインタ型で宣言していますわ
\footnotesize \textcolor{lime}{ずんだもん:} 足し算の結果を戻り値ではなく、ポインタを使って返しているのだ
\footnotesize \textcolor{pink}{四国めたん:} その通りですわ
\footnotesize \textcolor{pink}{四国めたん:} そして、関数add
の呼び出し側ではadd(&x, y);
のように アドレス演算子 &
を使って変数"x"のアドレスを渡していますわ
\footnotesize \textcolor{lime}{ずんだもん:} ポインタの引数には、変数のアドレスを渡すのだ
\footnotesize \textcolor{pink}{四国めたん:} このアドレスは、関数側ではコピーして使われますが、 間接演算子 *
により間接的に変数"x"にアクセスしていますわ
\footnotesize \textcolor{lime}{ずんだもん:} 結果として変数"x"の値は、足し算により3に変更されているのだ
\footnotesize \textcolor{pink}{四国めたん:} 今までの関数では、戻り値によって1つの値しか返すことができませんでしたわ
\footnotesize \textcolor{pink}{四国めたん:} でも、引数にポインタ型を使うことで、戻り値以外に複数の値を返すことができるようになりますわ
\footnotesize \textcolor{lime}{ずんだもん:} これはすごいことなのだ
戻り値にポインタ型を使う場合は要注意
\footnotesize \textcolor{lime}{ずんだもん:} ところで関数の戻り値にポインタ型を使用することは可能なのか?
\footnotesize \textcolor{pink}{四国めたん:} 結論からいえば可能ですわ
\footnotesize \textcolor{pink}{四国めたん:} ただ注意として、関数内で宣言した変数のポインタを返すことは御法度ですわ
\footnotesize \textcolor{lime}{ずんだもん:} そうなのか?
\footnotesize \textcolor{pink}{四国めたん:} 確認してみましょう
#include <stdio.h>
int* add(int a, int b) {
int c = a + b;
return &c;
}
void main() {
int x = 1;
int y = 2;
int* p = add(x, y);
printf("xとyの和は%dを期待します\n", (x + y));
printf("addによるxとyの和は%dです\n", *p);
}
\footnotesize \textcolor{pink}{四国めたん:} add
関数の内部で宣言した変数"c"のアドレスをポインタとして戻していますわ
\footnotesize \textcolor{lime}{ずんだもん:} 出力結果は、期待している値"3"とは異なる値が表示されているのだ
\footnotesize \textcolor{pink}{四国めたん:} 一見、正常に動作するように見えますが「C4172: ローカル変数またはテンポラリ:cのアドレスを返します」と云うワーニングが出ていますわ
\footnotesize \textcolor{lime}{ずんだもん:} どうして問題なのだ?
\footnotesize \textcolor{pink}{四国めたん:} 実は関数、正確に言えば波括弧"{}"で囲われたブロックの中で宣言された変数は、ブロックを離れるとメモリに対する割り当てが自動的に解除されますわ
\footnotesize \textcolor{lime}{ずんだもん:} つまり、変数が使えなくなるということか
\footnotesize \textcolor{pink}{四国めたん:} はい、関数内で宣言された変数は、関数外では使えなくなっています
\footnotesize \textcolor{pink}{四国めたん:} ですので、ポインタを使ってアクセスすると動作がおかしくなりますわ
\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ
\footnotesize \textcolor{pink}{四国めたん:} 今回は大した問題にはなりませんでしたが、最悪の場合はプログラムが暴走することになりますわ
\footnotesize \textcolor{lime}{ずんだもん:} たいへんなのだ
\footnotesize \textcolor{pink}{四国めたん:} C言語のポインタの取り扱いが難しく、判り難いと云われる所以でもありますわね
まとめ
\footnotesize \textcolor{pink}{四国めたん:} お疲れさまでした
\footnotesize \textcolor{lime}{ずんだもん:} おつかれさまなのだ
\footnotesize \textcolor{pink}{四国めたん:} メモリとポインタ についての説明は以上ですわ
Discussion