こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

コールバック関数はnullにならない?

頭がこんがらがっているので質問させてください。

int Func(int a){
}

という関数があって

void main(){
void* callbackAddress;
int iNum;
callbackAddress = Func;
stat =(*callBackAddress)(num);
}
のような場合、
callbackAddress = Func;の直後に
*callbackAddress = 0x00;
を挿入することはできないのでしょうか?

投稿日時 - 2005-04-07 16:41:26

QNo.1317216

暇なときに回答ください

質問者が選んだベストアンサー

>callBackAddress = null;だけチェックすれば*callBackAddress = null;(又は0x00)はチェックしなくてよいのでしょうか?関数のアドレスだからチェックしなくとも大丈夫なのでしょうか?

結論からいうとチェックしなくてかまいません。
関数へのポインターである場合に限り、
callBackAddressと*callBackAddressはおなじ値になります。
これは、通常のポインター(例えば int *a)の場合、以下の意味になります。
int *a ;
int x;
a = null;
a = &x;
if (a==null)はポインターがnullかを問うものであり
if (*a == null)(又は0x00)は、変数xの内容が0x00かを
問うものです。従って、全く違ういみのものです。
一方、関数へのポインターcallBackAddressの場合は
callBackAddressと*callBackAddressは同じ値となります。(Funcのアドレスを示します)
これは、不思議な感じがしますが、そのように定義されているようです。
callBackAddress = Func;
のあとで
printf ("%p\n",callBackAddress);
printf ("%p\n",*callBackAddress);
printf ("%p\n",**callBackAddress);
printf ("%p\n",Func);
としてください。
結果はすべて同じ値となります。

投稿日時 - 2005-04-07 22:23:13

お礼

なるほどこれですっきりしました。皆様、ありがとうございました。特にtatsu99様には丁寧なご説明感謝いたします。

投稿日時 - 2005-04-08 10:13:37

ANo.6

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(6)

ANo.5

>実は、単体テストをしていて、callbackAddressがnullのときにセグメントエラーが発生してしまったので、callbackAddressがnullのときの考慮が必要だなあと思ったのですが,ついでに*callbackAddressがnullの場合も考慮すべきかどうかというので悩んでおりました。NO.2の方の解答には納得です。

質問の主旨が判りました。
やりたいことは、関数へのポインターが未設定(=null)のときに、異常終了しないような仕組みをつくりたいということですね。以下のようにしてください。
------------------------------------
int (*callbackAddress)(); //関数へのポインタ宣言

callbackAddress = null; //まず、nullを設定しておく
・・・
・・・
callbackAddress = Func;//ある条件のときにFuncへのポインターが設定される。(しかし、必ずこのステップが実行されるとは限らない)
・・・・
if (callbackAddress == null){
//このケースは、未設定のケースだ。実際に呼び出してはいけない。エラーメッセージをだして、処理をうち切るのが普通のやりかた。
}else{
//OK、設定されている
stat =(*callBackAddress)(num);//実際に呼び出す。
}
---------------------------------
ちなみに
*callBackAddress = null;(又は0x00)
はやってはいけません。
callBackAddress = null;として下さい。

投稿日時 - 2005-04-07 20:25:09

補足

詳細にありがとうございます。callBackAddress = null;だけチェックすれば*callBackAddress = null;(又は0x00)はチェックしなくてよいのでしょうか?関数のアドレスだからチェックしなくとも大丈夫なのでしょうか?どうもすっきりしないのですが。。。

投稿日時 - 2005-04-07 20:39:22

ANo.4

なさりたいのは、
callbackAddress = Func;
*callbackAddress = 0x00;
stat =(*callBackAddress)(num);
のようにしたいと言うことでしょうか。
もし、そうであれば、No2の方が言及しているとおりです。
そのことにより、プログラムが異常終了しますが
あなたが、そのことを望んでいるとは、思えません。
本当になさりたいことは、何なのでしょうか。もしくは、どうして、このような質問をされたのでしょうか。その辺の状況を説明していただければ、もっと適切な回答ができるかと思います。

投稿日時 - 2005-04-07 18:26:13

補足

返信が遅れ,もうしわけありません。実は、単体テストをしていて、callbackAddressがnullのときにセグメントエラーが発生してしまったので、callbackAddressがnullのときの考慮が必要だなあと思ったのですが,ついでに*callbackAddressがnullの場合も考慮すべきかどうかというので悩んでおりました。NO.2の方の解答には納得です。

投稿日時 - 2005-04-07 19:21:54

ANo.3

突っ込みどころ満載ですが、それはさておき...

callbackAddressはvoid型へのポインタですので、このポインタを用いて間接参照することも関数を呼び出すこともできません。

関数が格納されているエリアを書き換えたいということであれば、(適切な文法に修正することで)可能ですが、何らかの事情(ROMであったり、MMUによるメモリ保護がかかっていたり)で書き換えが禁止されていたり、場合によっては同じアドレスに書き込みレジスタが配置されていたりすることもあり得ますので、何が起こるかはターゲットに依存します。言語仕様上はもちろん未定義です。

投稿日時 - 2005-04-07 17:12:13

ANo.2

 言語上はできます。
 そうすることに意味はありませんが。
 callbackAddress には Func 関数が存在する物理アドレスが入っているので、NULL(0x00) を挿入した状態で実行するとプログラムが停止します。(厳密には例外が発生します)

 OS上の制限により、アドレスゼロの領域を実行することはできないのです。

投稿日時 - 2005-04-07 16:56:47

ANo.1

*callbackAddress = 0x00;
ではなく、

callbackAddress = NULL;
では?

投稿日時 - 2005-04-07 16:46:56