こんばんは、川合です。 昨日[OSASK 6485]を書いているときに[OSASK 6484]が届いてちょっと 入れ違いになってしまいました。 KOYANAGI, Masaaki さんは 2003/09/24 23:57:49 の「[OSASK 6484] Re : FORM: 要望になってしまいますが.」で書きました: >アプリが大きくなってしまうのは、今のところ OSASK において、Cで書かれた >プログラムが DLL を使用することができず、printf* 系の関数もスタティック >リンクするしかないからというのも理由の一部かと思います。 >Linux では、*printf系は、libc.so にあって、ダイナミックリンクして >使われるのが普通ですし。 C言語で書かれたプログラムはDLLを利用できないとか、(これはこの メールには書いてありませんが)DLLはC言語では書けない、というのは 正しくない認識です。まあ、C言語だけでは書けない、というのなら確 かにそうですが。 ほんのちょっとだけASKAの助けを借りれば、DLLをC言語で書いたり、 呼び出したりできます。そもそも、今のAPIはDLLなわけで、みなさんC 言語で普通にAPIを利用しているのですから、DLLがC言語から利用でき ないということは、断じてありません。lib_execcmd()的な関数を、ASK Aでちょこっと作って橋渡しにさせればOKなのです。 ということでサンプルを作りました。test049です。ベータリリース してあります。sprintf()をDLLに追い出して、countdownをやって遊ん でいます。 >> 初心者は、printf()があるとどうしてもこれを使いたくなってしまい >> 、これに頼る傾向が出てくるでしょう。そうすると、setdec()のような >> ことをやる人が少なくなって、setdec()はなんだか知らないが高度なこ >> とだという誤った印象が広がって、結局みんなでかいアプリばかり作る >> というOSASKらしくない結論にいたる可能性があります。それだけが心 >> 配です。 > >これは上のスタティックリンクの件も含めてはっきりと説明して、その上で >アプリ製作者に判断を任せるというので問題ないでしょう。 それはよくないと思います。初心者はprintf()を最初に使えば、最後 までprintf()を使います。setdec()をつくろうなんて思いもよりません し、そもそも文字列というのは、charの配列であるという基本的なこと すら理解しないことがあります。文字列の長さはstrlen()じゃないと数 えられないとか、strcat()なしには連結できない、なんてプログラマが 知り合いにいました(それでもC言語のプログラミング歴1年以上なんで すが)。 まあよく言えば、彼は「文字列」というものを抽象化して理解してい たために、内部構造なんて気にもかけなかったのでしょう。だからでき なかったんだと思います。標準ライブラリばかり使うプログラミングに 最初に慣れてしまうと、こういうプログラムしか書けなくなるから、僕 は嫌なんです。 どんなに説明しても、printf()とsetdec()をいっしょに説明するなら 初心者は簡単なprintf()のほうだけを理解して、setdec()のほうを流し 読みします。そして理解してないsetdec()を使いませんし、あとで勉強 してみようという気にもなりません。そしてその人はいつまで経っても 駄目なプログラムを作り続けます。僕はそんなプログラムは「エミュレ ータを使わないで走るアプリケーション」くらいにしか思っていません 。ちっともOSASKらしくありません。OSASKアプリといったら、やっぱり 小さくて速いものであってほしいです。 今のOSASKが小さくて速いアプリにあふれているのは、まさにこの僕 の作戦が功を奏しているのです(もちろんOSASKのAPIの優位性も効いて いますが)。 しかし、何もかもちゃんとわかった上級者にprintf系の関数を提供す るというのには反対しません。だからベイサイドさんに使ってもらおう と思って、test047を作りました。この点においては、「説明して、そ の上でアプリ製作者に判断を任せる」というのに賛成です。 >説明の例 >(1)OSASK アプリケーションのエディタ teditc は 10kB 程度だが、それに比べて >*printf系の関数は??kBと大きい。 >(2)sprintf(buf, "%d %c %s", i, j, buf); を setdec() 他を用いて書き直すと >??kB の節約となる >(3)だからアプリケーションを書く場合は、*printf() は必要最小限にして欲しい > >実際のところ、問題としている sprintf() 関数はどれくらい大きいのですか? 面白いテーマだと思ったので、ちょっとやってみました。この手の考 察にはなると思います。 test048もベータリリースしてあるのですが、これには、GOでコンパ イルしたcntdwncとtest048が入っています。これにtest049を加えて、 こんな考察ができます。 まずこの3つのプログラムについてまとめます。 ・動作はみんな同じ ・cntdwnc : 414バイト setdec仕様 ・test048 : 1293バイト sprintf仕様(スタティックリンク) ・test049 : 629バイト sprintf仕様(ダイナミックリンク) (DLLは1034バイト) この場合%3dしか使っていません。ちょっとsprintf()には酷かもしれ ません。しかし例えばnaskもsprintfを使っていますが、%sも%cも使っ ていません(%dと%Xを多用している)。実用プログラムでsprintfがあ りがたいのは、%sや%c以外の変換でしょう。 とりあえずcntdwncとtest048の差を取ると、879バイトになります。 これが現状でのsprintfのコストだといえるでしょう。test049は414バ イトよりも215バイトも多いですが、これは今のOSASKのAPIのDLLサポー トが弱いせいです。予定しているDLLサポート用のAPIが追加されれば、 オーバヘッドは小さくなって、差は50バイトくらいで済むと思います。 DLL側の1034バイトというのは、多分変わりません。差の155バイトは、 DLLをまたぐオーバヘッドみたいなものです(その代わり、今のAPIと同 じくファンクションをキューで渡せますので、うまく使えば速度的なオ ーバーヘッドは最小になります)。 なお、この879バイトという差をどう思うかですが、僕はこれはまあ 我慢できないことはないと思います。しかし今のsprintf()はサブセッ トです。%fや%eをサポートする必要あります。これをサポートしたら、 2KB以上になるのは多分避けられないと思います。そしてそういうsprin tf()ができたら、きっとそちらを使うことになると思います。だから%d 程度のためにスタティックリンクでsprintf()を使うのは、OSASKアプリ としてはかなりよろしくない、ということになるでしょう。DLLならサ イズの問題はありません。sprintf()は処理が多くて重たい関数なので、 処理頻度の高いところに使うのはお勧めしませんが、そうじゃなければ 積極的に使っていいと僕は思います。 初心者は頻度の高いところにもsprintf()を使うので、というか、spr intf()しか理解しようとしないので、たとえDLLであってもsprintf()を 与えたくはありません。 >どうも [OSASK 6482] は、 > >「*printf() をスタティックリンクされるとアプリケーションのサイズが >大きくなるから、(川合さんは) *printf() という選択支を提供するのに気が >進まない」 > >と私には聞こえて納得できません。もう少し詳しい説明をお願いします。 ということで、僕がprintf族をことさらに嫌がっているのは、初心者 向けの教育上好ましくない、という点だけであります。ベイサイドさん や小柳さんやI.Tak.さんのような、その辺のことが何もかも分かってい る人は、小柳さんのいうとおり自分で正しい判断ができますので、提供 しない理由にはなりません。 僕は今までprintf()のサポートをするべきじゃないかという提案に対 して反対し続けてきたのは、その動機が「初心者がhello, worldするた め」だったからです。しかしベイサイドさんみたいな用途でということ なら(その苦労はよくわかりました)、僕は賛成しますし、手も貸すわ けです。 ということで、あとは初心者が初心者を脱するまで、sprintf()の存 在を知らないでいてくれることを強く願うばかりです。みなさんもアド バイスの際には極力言及しないようにしてほしいです。introaにstdio. hを入れないで、introeあたりにstdio.hだけ入れようかなと思っていま す。 それでは。 -- 川合 秀実(KAWAI Hidemi) OSASK計画代表 / システム設計開発担当 E-mail:kawai !Atmark! imasy.org Homepage http://www.imasy.org/~kawai/