prog_0001
の編集
https://k.osask.jp/klog/?prog_0001
[
トップ
] [
編集
|
差分
|
バックアップ
|
添付
|
リロード
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
-- 雛形とするページ --
2012_0001
2013_0001
2013_0002
2013_0003
2014_0001
2015_0001
2016_07
2016_08
2016_09
2016_10
2016_11
2017_01
2017_02
2017_03
2017_04
2017_05
2018_01
2019_01
BracketName
FormattingRules
FrontPage
Help
InterWiki
InterWikiName
InterWikiSandBox
K
KH_SARC_00
KH_dha8
MenuBar
PHP
PukiWiki
PukiWiki/1.4
PukiWiki/1.4/Manual
PukiWiki/1.4/Manual/Plugin
PukiWiki/1.4/Manual/Plugin/A-D
PukiWiki/1.4/Manual/Plugin/E-G
PukiWiki/1.4/Manual/Plugin/H-K
PukiWiki/1.4/Manual/Plugin/L-N
PukiWiki/1.4/Manual/Plugin/O-R
PukiWiki/1.4/Manual/Plugin/S-U
PukiWiki/1.4/Manual/Plugin/V-Z
RecentDeleted
SandBox
VC_install
WikiEngines
WikiName
WikiWikiWeb
YukiWiki
fdpl_memo0001
fdpl_memo0002
fdpl_memo0003
fdpl_memo0004
fdpl_memo0005
fdpl_memo0006
fdpl_memo0007
fdpl_memo0008
fdpl_memo0009
fdpl_memo0010
gg02_0004
gg02_0005
gg02_0006
gg02_0007
gg02_0008
gg02_0009
https
impressions
memo0001
memo0002
oisix01
osaskology
osaskology0
osecpu_0001
osecpu_0002
p20200229a
p20200303a
p20200310a
p20200321a
p20200401a
p20200730a
p20201230a
p20220628a
p20220701a
populars
prog_0001
prog_0002
prog_0003
prog_0004
prog_0005
* C言語における汎用的な関数 -(by [[K]], 2014.10.03) ** (0) -以前はoSasKdotにプログラミング一般系の話題を書いていたけれど、今は使えないので、書くところがない。 -ということでここに書くことにする。 ** (1) -たとえば<stdlib.h>のqsort()では、一般化された比較関数として、 int compare(const void *a, const void *b); -みたいなものを使っている。 -これは、任意の2引数関数を表現していると一般には思われている。でも僕はこれが十分ではないと思う。 -こんな状況を考えよう。すごくよく似た関数を100本書かなければいけないとする。それぞれの関数は95%は共通で違いはわずかだとしよう。このとき、関数をそのまま100個作れば話は単純でいいのだけど、そうしたらプログラムはむやみに長くなるし、バグも入り込んでしまうかもしれない。・・・そうであれば、関数を一つにして、引数を一つ増やして、その増やした引数で100個のどれなのかを選べるようにしたらどうだろう。このほうがずっといいと思う。 -となると、関数は本来の引数のほかに、関数をカスタマイズするための構造体のポインタが必要なんじゃないか、と考えた。 -つまりintを2つとる汎用関数ならこうなる。 int func(void *customize, int a, int b); -このスタイルを採用するのなら、qsort()はこうなる。 void qsort(base, num, size, compare, customize); -このcustomizeはcompareを呼び出すときに必ず渡される。つまり汎用の関数を渡すには、単に関数ポインタだけでは不十分で、カスタマイズ構造体のポインタが必要なのだ。 -これが今回の僕の主張である。 -ちなみに何も渡すデータがないのなら、customizeはNULLでいいし、compare関数もcustomize引数の値は無視すればいい。 ** (2) -ここで関数として、なんらかのVMというかインタプリタみたいなものを考える。そしてカスタマイズ構造体の中に、インタプリタで実行したいプログラムが入っているとする。これならたった一つの関数しかなくても、データだけ変えればどんな処理もできるということになる。 --まさに汎用的だ! ** (3) -機械語を実行時に動的に生成してもよければ、常にあるカスタム構造体を適用して呼び出すような関数を自動生成することはできる。 void *makeFunc(void *baseFunc, void *customize, int x, int y) { p = mallocして、実行権限を付ける. メモリに機械語を書いて、f(x,y) { return baseFunc(customize, x, y); } に相当する関数を作る. return p; } -だからこれを前提にすれば、カスタマイズ構造体へのポインタを含まなくても、関数のポインタだけで汎用性を確保することはできる。 -でもこの処理はもちろんコンパイラ的な処理が必要なので機種依存する。関数呼び出しの深さも増えているので、オーバーヘッドもある。 * こめんと欄 -(1)は関数型言語での「クロージャ」に近い発想ですね。Cだと関数から引数以外に見える外界はグローバルスコープだけですが、クロージャを備えた言語なら例えば「[=](int a, int b) -> int { return func(customize_000, a, b); }」という式を書けば、(ローカル変数かもしれない)customize_000をfuncの第1引数に固定して呼び出す関数への関数ポインタが得られます(KさんならCに近い言語が分かりやすいと思ったのでこの例はC++0xです)。コンパイラの実装次第ですが、voidポインタを持ち回るのとだいたい同等のコードが生成されそうです。(3)と同じ動作としては「カリー化」という概念があります。さすがに動的に機械語を生成する実装は知りませんが、ヒープに確保した(カスタマイズ構造体に相当する)データ構造に固定する引数を保持する実装が主流だと思われます。オーバーヘッドより移植性を重視するのが近年の流れでしょうか。 -- ''yao'' SIZE(10){2014-10-07 (火) 18:28:16} -おお、yaoさんありがとうございます! -- ''K'' SIZE(10){2014-10-14 (火) 10:58:21} #comment
タイムスタンプを変更しない
* C言語における汎用的な関数 -(by [[K]], 2014.10.03) ** (0) -以前はoSasKdotにプログラミング一般系の話題を書いていたけれど、今は使えないので、書くところがない。 -ということでここに書くことにする。 ** (1) -たとえば<stdlib.h>のqsort()では、一般化された比較関数として、 int compare(const void *a, const void *b); -みたいなものを使っている。 -これは、任意の2引数関数を表現していると一般には思われている。でも僕はこれが十分ではないと思う。 -こんな状況を考えよう。すごくよく似た関数を100本書かなければいけないとする。それぞれの関数は95%は共通で違いはわずかだとしよう。このとき、関数をそのまま100個作れば話は単純でいいのだけど、そうしたらプログラムはむやみに長くなるし、バグも入り込んでしまうかもしれない。・・・そうであれば、関数を一つにして、引数を一つ増やして、その増やした引数で100個のどれなのかを選べるようにしたらどうだろう。このほうがずっといいと思う。 -となると、関数は本来の引数のほかに、関数をカスタマイズするための構造体のポインタが必要なんじゃないか、と考えた。 -つまりintを2つとる汎用関数ならこうなる。 int func(void *customize, int a, int b); -このスタイルを採用するのなら、qsort()はこうなる。 void qsort(base, num, size, compare, customize); -このcustomizeはcompareを呼び出すときに必ず渡される。つまり汎用の関数を渡すには、単に関数ポインタだけでは不十分で、カスタマイズ構造体のポインタが必要なのだ。 -これが今回の僕の主張である。 -ちなみに何も渡すデータがないのなら、customizeはNULLでいいし、compare関数もcustomize引数の値は無視すればいい。 ** (2) -ここで関数として、なんらかのVMというかインタプリタみたいなものを考える。そしてカスタマイズ構造体の中に、インタプリタで実行したいプログラムが入っているとする。これならたった一つの関数しかなくても、データだけ変えればどんな処理もできるということになる。 --まさに汎用的だ! ** (3) -機械語を実行時に動的に生成してもよければ、常にあるカスタム構造体を適用して呼び出すような関数を自動生成することはできる。 void *makeFunc(void *baseFunc, void *customize, int x, int y) { p = mallocして、実行権限を付ける. メモリに機械語を書いて、f(x,y) { return baseFunc(customize, x, y); } に相当する関数を作る. return p; } -だからこれを前提にすれば、カスタマイズ構造体へのポインタを含まなくても、関数のポインタだけで汎用性を確保することはできる。 -でもこの処理はもちろんコンパイラ的な処理が必要なので機種依存する。関数呼び出しの深さも増えているので、オーバーヘッドもある。 * こめんと欄 -(1)は関数型言語での「クロージャ」に近い発想ですね。Cだと関数から引数以外に見える外界はグローバルスコープだけですが、クロージャを備えた言語なら例えば「[=](int a, int b) -> int { return func(customize_000, a, b); }」という式を書けば、(ローカル変数かもしれない)customize_000をfuncの第1引数に固定して呼び出す関数への関数ポインタが得られます(KさんならCに近い言語が分かりやすいと思ったのでこの例はC++0xです)。コンパイラの実装次第ですが、voidポインタを持ち回るのとだいたい同等のコードが生成されそうです。(3)と同じ動作としては「カリー化」という概念があります。さすがに動的に機械語を生成する実装は知りませんが、ヒープに確保した(カスタマイズ構造体に相当する)データ構造に固定する引数を保持する実装が主流だと思われます。オーバーヘッドより移植性を重視するのが近年の流れでしょうか。 -- ''yao'' SIZE(10){2014-10-07 (火) 18:28:16} -おお、yaoさんありがとうございます! -- ''K'' SIZE(10){2014-10-14 (火) 10:58:21} #comment
テキスト整形のルールを表示する