デジタルちんぶろぐ

デジタルな話題

ホーム 連絡をする 同期する ( RSS 2.0 ) Login
投稿数  268  : 記事  0  : コメント  4375  : トラックバック  79

ニュース


技術以外は
ちんぶろぐ

記事カテゴリ

書庫

日記カテゴリ

関数ポインタ。

いつもtypedefしているから関数ポインタを返す関数を書くことで悩むことが無かった。
否、悩みたくないから関数ポインタをtypedefしていたという方が正しいでしょう。

ではtypedefを使わずに関数ポインタを返す関数を書く、且つその関数へのポインタの型を書くことは出来るのか(言語としてではなく自分の知識としてです)

以下のようなプログラムを書いて段階的に難しくなるようにしてみました。基本的にCでもC++でも変わりませんが、C++ではtypeidがあるので型名を取得できます。
折角なのでその機能を利用し、C++環境ではよりわかりやすい出力結果が出るように してみました。

※このプログラムはCでもC++でもどちらでもコンパイルできるようにしてあります。ここに載せている実行結果はVC2008のものです。

#ifdef __cplusplus
#include <cstdio>
#include <typeinfo>
using namespace std;
#else
#include <stdio.h>
#endif

#ifdef __cplusplus
#define SHOW_TYPE(func, var) func; printf("%-30s %s\n", #func, typeid(var).name())
#else
#define SHOW_TYPE(func, var) func;
#endif

/* 関数ポインタで呼び出される関数本体 */
void foo(int i) { printf("foo(%d);\n", i); }
void bar(void (*f)(int), int i) { printf("bar(%p, %d); ", f, i); f(i); }
void (*foo_getter(void))(int) { printf("foo_getter(); "); return foo; }
void (*foo_returner(void (*f)(int)))(int) { printf("foo_returner(%p);", f); return f; }

/* 関数ポインタ */
void (*foo_v)(int) = foo;
void (*foo_vs[1])(int) = { foo };

/* 関数ポインタを引数としてとる関数へのポインタ */
void (*bar_v)(void (*)(int), int) = bar;
void (*bar_vs[1])(void (*)(int), int) = { bar };

/* 関数ポインタを戻り値とする関数へのポインタ */
void (*(*foo_getter_v)(void))(int) = foo_getter;
void (*(*foo_getter_vs[1])(void))(int) = { foo_getter };

/* 関数ポインタを引数として取り関数ポインタを戻り値とする関数へのポインタ */
void (*(*foo_returner_v)(void (*)(int)))(int) = foo_returner;
void (*(*foo_returner_vs[1])(void (*)(int)))(int) = { foo_returner };
int main()
{
    SHOW_TYPE(foo_v(1), foo_v);
    SHOW_TYPE(foo_vs[0](2), foo_vs);
    SHOW_TYPE(bar_v(foo, 3), bar_v);
    SHOW_TYPE(bar_vs[0](foo, 4), bar_vs);
    SHOW_TYPE(foo_getter_v()(5), foo_getter_v());
    SHOW_TYPE(foo_getter_vs[0]()(6), foo_getter_vs[0]());
    SHOW_TYPE(foo_returner_v(foo)(7), foo_returner_v(foo));
    SHOW_TYPE(foo_returner_vs[0](foo)(8), foo_returner_vs[0](foo));

    return 0;
}

Cでの実行結果
foo(1);
foo(2);
bar(00401000, 3); foo(3);
bar(00401000, 4); foo(4);
foo_getter(); foo(5);
foo_getter(); foo(6);
foo_returner(00401000);foo(7);
foo_returner(00401000);foo(8);

C++での実行結果
foo(1);
foo_v(1)                       void (__cdecl*)(int)
foo(2);
foo_vs[0](2)                   void (__cdecl*[1])(int)
bar(00401000, 3); foo(3);
bar_v(foo, 3)                  void (__cdecl*)(void (__cdecl*)(int),int)
bar(00401000, 4); foo(4);
bar_vs[0](foo, 4)              void (__cdecl*[1])(void (__cdecl*)(int),int)
foo_getter(); foo(5);
foo_getter_v()(5)              void (__cdecl*)(int)
foo_getter(); foo(6);
foo_getter_vs[0]()(6)          void (__cdecl*)(int)
foo_returner(00401000);foo(7);
foo_returner_v(foo)(7)         void (__cdecl*)(int)
foo_returner(00401000);foo(8);
foo_returner_vs[0](foo)(8)     void (__cdecl*)(int)

尚、gcc/g++でのプログラムと実行結果は以下のリンク先にあります
(g++でマングリングされた型をわかりやすくするためソースに手が入れてあるので)

gcc
http://ideone.com/lpOfq

g++
http://ideone.com/AC4il

投稿日時 : 2010年8月4日 2:07

コメント

# HQCTMvMtTH 2011/12/22 21:26 http://www.discreetpharmacist.com/
is7U38 Strange but true. Your resource is expensive. At least it could be sold for good money on its auction!...

# re: Ruby で数値を 0 埋めする 2019/01/24 13:44 zzyytt
http://www.goyard.us.com
http://www.stephencurry.us.com


# re: Ruby で数値を 0 埋めする 2019/01/24 13:45 zzyytt
http://www.offwhitehoodie.us.com
http://www.nikereact.us.com
http://www.michaelkors-outletfactory.us.org


# affordable care act information std list and symptoms men WordPress 2019/09/05 7:36 buy provigil usa
Very good article. I absolutely love this site. Thanks!

# iaqHunQuiC 2022/04/19 11:45 johnanz
http://imrdsoacha.gov.co/silvitra-120mg-qrms

Post Feedback

タイトル
名前
Url:
コメント: