パスワードを忘れた? アカウント作成
この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。

C#言語、ISO標準獲得へ」記事へのコメント

  • ISO標準ってなにか意味があるのでしょうか?

    よく分からないのですが、今のところ.NETフレームワーク以外に使用されるようなことはなさそうですし、標準でなくていいからMSのほうで勝手にやっていてくれという感じです。

    ちなみに、

    C#に置き換わり、C++は廃れてしまったりするのでしょうか

    そんなことないと信じています。

    というか、C#ってC++

    --
    // Give me chocolates!
    • > ISO標準ってなにか意味があるのでしょうか?

      ISOになると、各国政府がある程度の後押しをすることになってます。

      例えば、おそらくJISにもなるでしょうし、情報処理技術者試験の
      選択科目にもなるかもしれません。さらにひょっとしたら、中学や
      高校の授業でとりあげられるかもしれません。

      今すぐの影響は
      • by brake-handle (5065) on 2002年10月15日 22時19分 (#183855)

        30年どころか、100年たっても間違いなく生き残るであろう言語が少なくとも2つはあるでしょう。アセンブラとCです。

        これらの言語の特異な点は、言語のsemanticsに面倒な実行時の支援処理や初期化が一切含まれていないことです。すなわち、自分で作ったエントリポイントにいきなり処理を飛ばしてもきちんと動作するわけです。これは計算機をbootさせるためには必ず通らなければならない関門であり、ほかの言語にはマネができません。どんなにプログラムが組みにくくても、この2言語だけは捨てることはできないでしょう。

        もっとも、アセンブラがどういう言語かという問題は残りますが、LispマシンだったらLispがアセンブラのようなものですしね。

        親コメント
        • by bnez (11270) on 2002年10月15日 23時46分 (#183921) ホームページ
          > 30年どころか、100年たっても間違いなく生き残るであろう
          > 言語が少なくとも2つはあるでしょう。アセンブラとCです。

          アセンブラが当分生き残るということには同意しますが、100年と言われるとちょっとどうかなあという気が。

          アセンブラはノイマン型コンピュータの最下層のソフトウェア(を人間に可読な表記にしたもの)ですから、ノイマン型コンピュータと一蓮托生です。その意味で、ご指摘の通りアセンブラの寿命が非常に長いというのはほぼ間違いないでしょう。が、ノイマン型コンピュータがあと100年持つかどうかというと、それにはちょっと漠然とした疑問があります。確かに今のところ不動の地位を保っていますが。

          また、Cは「アセンブラの体のいいwrapper」としての側面が強く、今さらCと同じ立場を置き換える言語が現れることもないでしょうから、アセンブラとCは同じ寿命を持つと思います。この点はそのまま同意です。

          もしノイマン型コンピュータを駆逐するような制御構造が現れたとすると、記述の抽象度が高い関数型言語や論理型言語の方が案外生き残りやすいかもしれません。
          # ただの妄想かも
          親コメント
          • ノイマンを覆すようなパラダイムについては、夢を語るぐらいならやってみてもいいでしょう。ですが、商売として成り立つかというと、私は悲観的な見方をしています。

            計算機を買ってくれそうなお客さんというのは、まず第一に処理速度を見ます。過去、関数型や論理型で攻めた人達はプロセッサの数を増やすことでお客さんに買ってもらおうとしました(そもそも言語が大量の記憶域を仮定していたため、メモリやディスクを買い足す発想がなかった)。ところが、このアプローチの場合、データをロックするために必要なコストの見積もりが難しく、一定の性能を達成することが困難でした。

            一方、ノイマンで押した勢力は、メモリやディスクを増やしただけスケールアップするようなシステムを目標としていました。この場合、メモリやディスクの管理に必要なコストはプロセッサの場合よりもはるかに確実な見積もりがとれます。かくして、一定の性能を容易に達成できるだけでなく、処理能力の制御までも可能になりました(リアルタイムはその典型)。

            いくら夢があるものでも、暴れ馬ではお客さんに売りたくなるようなものにはならないでしょうね...

            親コメント
            • > ノイマンを覆すようなパラダイムについては、
              > 夢を語るぐらいならやってみてもいいでしょう。
              > ですが、商売として成り立つかというと、私は
              > 悲観的な見方をしています。

              それはそうです。現時点や予測可能な近い未来についてであれば、専用用途ではなく汎用用途においてノイマン型を上回るものは存在しないでしょう。性能・開発効率・費用対コスト・ソフトウェア資産量などの観点からノイマン型が合理的だからです。

              私の意見はただ単に、現状で考えられる条件で100年も先のことは予想できないかな、と考えたって話でして。

              ついでに関数型言語や論理型言語については、生き残りやすいかもしれないけれど主流にはならないと思います。新しいハードウェアに適した構造を持つ言語が開発されて、新しい主流になるんではないかと。その方が性能面で有利でしょうから。
              親コメント
            • > ノイマンを覆すようなパラダイムについては、夢を語るぐらいならやってみてもいいでしょう。
              > ですが、商売として成り立つかというと、私は悲観的な見方をしています。

              量子コンピュータやDNAコンピュータは?
              得意分野が違うんで、ノイマン型を覆すってことにはならないと思うけど、
              商売としては成り立つんじゃないの?
              DNAコンピュータはすでに実用化 [olympus.co.jp]もされてるし。
              このオリンパスの製品のように、ノイマン型と非ノイマン型は補完し合ってくもんだと思うけど、
              100年後にいまだにノイマン型が主流か、といわれると断言できないと思うな。

              #どうでもいいが、「遺伝子解析用DNAコンピュータ」の「電子計算部」って、どうみてもDELLのPCだよな。
              親コメント
          • ハードウェアの設計で用いるHDLは、
            非ノイマン型のアーキテクチャのための言語です。
            ハードウェアですので、すべてが並列に動作します。

            で、C言語のコードをHDLに変換するものがすでに存在しています。
            (詳細は、googleってください)

            CのコードからアセンブラやHDLが生成できるとなると
            重要なのは、言語では無くて思想なのかもしれませんね。
            親コメント
            • # ますますオフトピだな...

              > で、C言語のコードをHDLに変換するものがすでに
              > 存在しています。

              おそらく、System-Cなどに代表される「C言語をハードウェア記述言語として用いる開発環境」のお話かと思います。

              私見かもしれませんが、C言語がHDLに採り入れられるようになって来たのは、Cがハードウェア設計に向いているからではなく、別の理由によるものではないかと思います。

              C言語をHDLとして使う試みは4~5年前ぐらい(もっと前?)からありますが、一部の現場で使用されるようになってきたのは最近(1~2年前ぐらいから?)の話だと思います。採用されるようになった理由は、
              • 設計しているハードウェア上で動作するソフトウェアとの親和性が高い
              • タイミングを考慮しないシミュレーションが高速
                (ごく簡単に言えば普通にコンパイルして普通に実行するだけ)
              • 「Cが書ければハードウェア設計もできちゃいます」論法で開発環境が売れる
              あたりにあるんではないかと。SoC(System on Chip: 既存のコアに周辺デバイスを開発してくっつけて1チップ化したもの)開発においては最初の利点が活かされやすいですが、ハードウェア設計の本質で利点があるってわけじゃないです。むしろ、本来のCの持つ制御構造を並列化して回路に展開する過程でかなり無理をしているように思えます。
              # 怪しげなので識者・経験者のツッコミ歓迎

              ということで、私はC言語は非ノイマンな用途への流用にはあまり向いていないんじゃないかな、と思います。
              親コメント
              • 識者ではないですが・・。

                >C言語をHDLとして使う試みは4~5年前ぐらい(もっと前?)から
                >ありますが、一部の現場で使用されるようになってきたのは
                >最近(1~2年前ぐらいから?)の話だと思います。
                >採用されるようになった理由は、

                わたしは、ハードウェアの設計が出来る人間が少ないし、増えにくいので、
                計算機言語の論理などを理解できるソフトウェア技術者をハードウェアの
                設計者に転用するための方便だと思っています。

                #ま、(Cからの変換とは言え)HDLが書けるだけではハードウェアの設計は
                #完了しないので、HDLを作った後にいろいろ他のシミュレーションするの
                #からは、逃れられはしないんですけどねぇ・・・。
                --
                ---- redbrick
                親コメント
        • by rti (659) on 2002年10月15日 22時46分 (#183872) ホームページ
          私はそうは思いません。

          アセンブラについては CPU が存在している限り消えないでしょうが、
          C言語に関してはスレッドもサポートしていない言語が
          30年、100年後に生き残っているとは思えません。

          もし、残っているとしても、今の COBOL 並みの地位にいると思います。

          boost が取り込まれた C++ は生き残っていくような気がします。
          ただし、デスクトップというより、むしろ組み込み系、
          今のアセンブラ地位の言語として生き延びていくと思います。
          --
          by rti.
          親コメント
          • by brake-handle (5065) on 2002年10月15日 23時35分 (#183910)

            Cが今まで生き延びてきた、そしてこれからも生き延びていけるであろう本質は、後から追加が必要になった機能を全てlibraryに押し込めることができるためです。決して新しい機能のために言語の文法や意味論に手を加え、それゆえに過去のsourceを捨ててしまうようなことをしなかったのが強く効いています。その点では、threadingなんか1996年にとっくに実現されているのです。しかも、それ以前に作られたsourceを一切壊さずに。

            似たようなところでは、memory allocatorがあります。Cには汎用的なmemory allocatorとしての意味を持つ要素は一切ありません。高々stack上にとれる配列ぐらいです。これは実装が非常に簡単で、stack pointerの加減算ができればすぐに実現できます。一方、C++は汎用的なmemory allocatorの意味を持つnewとdeleteを定義してしまいました。したがって、C++を走らせる環境に応じてmemory allocatorを作り直さなければなりません。しかし、我々はいつでも4GBのだだっぴろい空間が使えるわけではありません。ページ数が限られているがゆえ、backing storeを作らなければ実用にならない環境にも直面します。わざわざそんな環境でまで、C++を走らせたいですか?

            Cがアセンブラとともに持っている専売特許は、環境への適応性です。memory allocatorなんかなくてもいい、単にRAMにloadしてentryへ飛び込むだけで実行できるプログラムを作れる言語がなければ、OSのような基本ソフトウェアは絶対に作れません。そもそも、メモリ管理をするプログラムをmemory allocatorが必要な言語で作ったりすることがタマゴとニワトリ問題を引き起こすので、そんなものを選ぶのはナンセンスですが。

            親コメント
            • >OSのような基本ソフトウェアは絶対に作れません
              BeOSはC++で記述されていたと思いましたが....。
              NeXTはObjective-Cで記述してたのでは?
              ま、どちらもCの記述がそのまま使えるから、要の所はCだ、と言われればそれまでですけど。
              親コメント
              • > >OSのような基本ソフトウェアは絶対に作れません
                > BeOSはC++で記述されていたと思いましたが....。
                > NeXTはObjective-Cで記述してたのでは?

                OSというよりはKernelについていいたかったのでは。
                BeではKernelコードではC++は使えないし、NeXTはmachカーネルですよね。
                親コメント
              • 要がCっぽいというのもありますけど、それ以上に注目すべきはそれらのOSで作られたcomponentが実際にはほかのOSでは一切役に立たなかったことでしょうね。片や完全にCで実装したMach VMはBSDにも移植できたというのに。

                C++だけじゃなくてオブジェクト指向の落とし穴なんですが、再利用性なんて形をきっちり決めただけじゃ全然実現できないんです。むしろ、外側から見える形に合わせて再利用元を変更するハメになったりして、本末転倒です。言語を設計する側にとってはもの作りのネタになりますが、その上で何十年も保守しなければならないものを作る側としてはまず採用できません。

                親コメント
              • >C++だけじゃなくてオブジェクト指向の落とし穴なんですが、再利用性なんて形をきっちり決めただけじゃ全然実現できない

                それ、OOが「害」になった、とまで強く言えるんでしょうか?

                もしそうでないなら、OOが有っても無くてもせいぜい同じ、という程度のことでしょうね。

                で、便利なものは使います。
                Vector(動的配列)「クラス」(のObject)が無かったらウンザリするよね、
                毎回似たようなコードを書いてたら日が暮れるよね、
                しかも似てるけど違う性質の(つまり兄弟の)クラスとかとも一緒に(=多態して)使いたいよね、
                とか言い出したら、せめてOOくらい無いと辛いですね。

                もちろん、辛かろうがどうしようが茨の道を歩む「自由」は有りますが。

                「再利用性」そのものの神話については、たしかにあれは神話でしかないですね。
                しかし、逆にいえば、OOを捨てたところで何かが楽になるわけでも無いわけで。
                それに、べつにOO(PL)だからって必ずガチガチの設計&再利用オタクに陥らないとならないわけじゃないです。

                >んです。むしろ、外側から見える形に合わせて再利用元を変更するハメになったりして、本末転倒です。

                そういうことはCだって生じることでは? Cに関数と構造体が有るからには、
                再利用性の問題は、クラス(関数と構造体と幾つかの追加オヤクソクの集成物でしかない)
                が有る言語と同じくらいに、ついて回るはずです。

                たとえば継承(再利用120%の世界)はイタイから必要最小限にしたほうがいい、ってのは
                OO内輪ですら既に言い尽くされた話です。OO人だってそれくらいの自衛策は心得てます。
                無策で取り掛かれば火傷するのは、どの言語や方法論(?)だって、同じ。

                稀に誤解してる人が居ますが、再利用といっても、実際にゃ大型や中型の部品は土台再利用しにくいんですよね。
                振り返って冷静に考えればCoding始める前から判りきってる事ではあるんだけど、
                システム全体のアーキテクチャに関わるような大きなObject(のクラス)は、一品物と思ったほうがいい。
                そして、逆に小さい部品の再利用性は、有効であることが多い。
                あたかもネジや釘のような小さくて「イロ」のついてない部品は再利用しやすい。
                ここを押さえていれば、再利用性自体は、そんなに御し難いものになったりはしない、んだけどなあ。

                大きな一品物をObject(Class)として作るのは、むしろ再利用性のためじゃなく、
                「そのほうがうまくまとまる物」であればObjectにするのが良いぞ、という感じだと思います。
                今自分が作ろうとしているプログラムがどういう性質のものであるか、によって決まると思います。
                ちょうど、ある処理を関数にする基準を、必ずしも「同じ処理の登場回数の多さ」だけで決めないほうがいい、のと同じです。
                #もちろん、小さい部品も、同じような調子で、Objectにするほうが似合うものと、そうでないものとがあります。

                余談:
                ところでC++以外のOOP言語は、どれくらい親しまれています?

                >その上で何十年も保守しなければならないものを作る側としてはまず採用できません

                それは変ですね。関数という部品の再利用は、(Cを使ってるからには)肯定されているのではないのですか?
                親コメント
            • >後から追加が必要になった機能を全て libraryに押し込めることができるためです。

              残念ですが全てではありません。
              上(?)で書いたように、Stackの使い方とかは処理系お仕着せになっちゃいますよね。

              ある実装のコンパイラのStackの使い方が不都合だからそれを捨てて違う実装を選ぶことは可能でしょうけど、
              それだってその処理系「の」お仕着せであるのは同じ。
              Cそのものの能力としてプログラマブルであるわけではないですよね。

              #俺のような、Cのたいした使い方をするわけでもない奴でも、時としてその「制限」が不快になります。

              そして、ここではたまたま「Stack」について書きましたが、
              そういうお仕着せによる制限は、C言語には、たしか他にも幾つかありますよね。
              確かにCは、お仕着せが他の多くの言語より「少なめ」ではあるんですが、「無い」わけではない。

              ここで「無い」なんて言い切っちゃうと、ほげ言語のパラドックス [dreamhost.com]の餌食になるのがオチです。

              >決して新しい機能のために言語の文法や意味論に手を加え、それゆえに過去の
              >sourceを捨ててしまうようなことをしなかったのが強く効いています。

              それは逆でしょう。
              Cが万能なのじゃなく、巷の多くのソフトが長年にわたって、Cの流儀にあわせてくれたんでしょう。
              Cでやれる範囲のことしかやらないようにしてきた、ということでしょう。

              Cは確かに万能ではなくても千能?くらいは有る言語なんで、そういう妥協をしても
              不都合が「あんまり」生じないわけですが、不都合は全く無いというわけじゃないです。

              >その点では、threadingなんか1996年にとっくに実現されているのです。しかも、それ以前に作られたsourceを一切壊さずに。

              #threadingって、(Multi)Threadのことですよね?違ったら御免。

              事情は全く知りませんが、それ、そういうものなのですか?
              96年という年は、Threadという"基本的な"ものが実装されるにしては遅すぎる時期であるような気がします。

              それに、「一切壊さず」ってのは無理が有りますよね。
              Threadが導入されればアプリ(など)側のアーキテクチャすら変わるのに、
              そのアプリ(など)のソースが無事でいられる筈が無いのでは?

              #そういやたしかちょうどその頃、そういうテーマの本を本屋で見かけた記憶が。
              #あの頃のイタイケな俺は驚いたもんだったけど、他の幾つかの言語を知った今となっては、もうあんまり驚けないな。

              >似たようなところでは、memory allocatorがあります。Cには汎用的なmemory allocatorとしての意味を持つ要素は一切ありません。

              というか、memory allocator「は」Cではライブラリとして提供「できる」機能(の1つ)ですね。
              他にも幾つか、Cにはそういう機能はあります。

              が、Cではライブラリの形態で提供できない機能「も」世の中には沢山有るわけで。

              たとえばLoopとかIfとか。

              また、前述のようにStackの使い方を変更したい場合があるので、「関数」という仕組み自体もまた
              場合によっては自作したりカスタマイズしたりライブラリ化したりしたいものですが、これも不可能ですよね。

              ここで「そんな機能を自作する必要は(滅多に)無い」という話をしてしまうと、
              Cの特徴もしょせんは程度問題だったのだということになります。

              >一方、C++は汎用的なmemory allocatorの意味を持つnewとdeleteを定義してしまいました。したがって、C++を走ら
              >せる環境に応じてmemory allocatorを作り直さなければなりません。しかし、我々はいつでも4GBのだだっぴろい空間が使え
              >るわけではありません。

              ん?そういうレベルの自作をアリだというならば、問題は簡単じゃありませんか?
              C++だって、とりあえず間に合う程度のお粗末なallocatorを作って与えればいい、ってことなのでは?

              >わざわざそんな環境でまで、C++を走らせたいですか?

              べつにCの後釜がC++でなきゃならんわけじゃないので、C++が不都合ならC++を捨てるまでです。
              つまりたまたまC++が例として不適切だっただけでは?
              親コメント
              • が、Cではライブラリの形態で提供できない機能「も」世の中には沢山有るわけで。
                たとえばLoopとかIfとか。

                制御構造がないのはプロセッサとして失格、マル。

                ん?そういうレベルの自作をアリだというならば、問題は簡単じゃありませんか?
                C++だって、とりあえず間に合う程度のお粗末なallocatorを作って与えればいい、ってことなのでは?

                あなたは恐ろしい人ですね、そのallocatorが実はOS全体で使うallocatorになってしまうことに気が付かないとは。

                OSの中でallocateする必要があるmemoryの大きさは、数十バイトから数GBまで非常に大きなばらつきを持っています。malloc(3)のように空のmemoryを持ってくるallocatorが実用になるのはせいぜい数十KBだけで、それ以上になると空きページを圧迫して性能を落としかねません。また、MB級になると全てを使い切らず、sparseにたたいていくことも増えてきます。

                そういう需要の方が実は性能に大きく響くことが分かっているから、複雑な機能を持つVMをいろいろ作ったわけです。仕様は後から変えると困る人が増えるだけに、単純にnewとdeleteで片付けているとひどい目に遭いますよ。

                親コメント
              • >「関数という仕組み自体を自作したりライブラリ化したり」ってなんのこっちゃ。G7たんは言語仕様って言葉わかってるか?

                若輩者な俺ですが敢えて言わせて頂くならば、
                「言語作ってみたことがあれば判りますよ。
                それも、Cとかみたいな有り触れた(ってのも変だが)言語とはあまり似てない言語を、ね。」
                です。

                勿論、洞察力のあるかたでしたら、わざわざ作るまでもなく理解可能かとも思います。
                つまり俺は作ってしまったわけですが(笑)。

                言語仕様ですか?
                それは、(現在の計算機で可能な)任意のかたちに「定義」可能です:-D。
                それとも、「関数という仕組み自体を自作」するような言語が
                現在の計算機で実現不可能だ、とでも思ってらっしゃる?

                よければLinkを書いておいた"PracticalScheme"頁を読んでおいてください。
                まぁあっちは俺も先日やっと知り始めた分野なんで受け売り100%ですが、
                逆にいえばそれだけ俺という劣悪フィルタを経由してません(ぷ

                >Cにスレッドが導入されたからって、スレッド使わないソースはそのままで問題ないだろ。

                あ。そうか。「使わない」部分の話だったのか。そう読めませんでした(^^;。

                >C#がJavaの出来損ないである

                それは嘘でしょう。出来損ない度でいえばJavaもC#も似たようなもんです。
                C#が流行り損なう可能性は否定しませんけど(笑)。
                親コメント
              • >制御構造がないのはプロセッサとして失格、マル。

                #プロセッサってなんですか?

                「ない」とは言ってませんけど。
                作ればいいしょ?と言っているのであって。
                #まぁ、毎回自作する事には意味は無いでしょうけど。

                >あなたは恐ろしい人ですね、そのallocatorが実はOS全体で使うallocatorになってしまうことに気が付かないとは。

                あれ?そういえば、C++のnewって、複数用意して使い分けることが出来るんじゃなかったっけ?

                #蛇足だがDelphiではNewInstanceというClassメソッド「を」多態することで同じことを実現できる。

                #蛇足2。Delphiは、メーカの言葉を信じるならば、Delphi自身と「アセンブラと」で作られてるそうな。C無し。
                ##Delphiを作るためにはCのStackFrame制限を回避する必要が有るそうなので、Cじゃ実際困るのでしょうね。
                親コメント
        • なんか言語の仕様の話と処理系の話と OS の話がごちゃまぜですよ。
          言語の semantics を考えるときは、その言語の色々な実装(例えば C言語だったら
          C インタプリタ)でその話が成り立つかどうかを考えるべきです。

          > これらの言語の特異な点は、言語のsemanticsに面倒な実行時の支援処理や初期化が
          > 一切含まれていないことです。すなわち、自分で作ったエントリポイントにいきなり
          > 処理を飛ばしてもきちんと動作するわけです。これは計算機をbootさせるためには必
          > ず通らなければならない関門であり、ほかの言語にはマネができません。どんなにプ
          > ログラムが組みにくくても、この2言語だけは捨てることはできないでしょう。

          一般的なコンパイラ出力の C 処理系のみを考えても、
          スタートアップコードを必要とします。これは C 以外のもので書かれていますよね。

          また、エントリポイントに飛ぶ機能を持った言語は、普通 自分で作ったエントリ
          ポイントに安全に飛ぶことができます(Lisp とか VB とか)。

          重要なのは C 言語のエントリポイント、つまり関数呼び出しが、CPU と OS によって
          決まる Application Binary Interface (ABI)と一致している(あるいは ABI を C の関
          数呼び出しに一致させている)ことではないですか?
          そういう言語の中で 1番 普及している言語として、C 言語が生き残ると。

          # 個人的には、C のデータ構造を ABI に合わせるための処理(register spill とか)
          # は実行時の支援処理といえると思います。
          # すでに G7 さんが指摘されていますが可変長引数や alloca などのスタックの使い方
          # もそうです。そして C9X はさらに進む。

          私なら、こう書きます。
          「 C の言語とその一般的な処理系の特徴は、OS の ABI を強く意識した関数呼び出しを
              持つこと。そのため、OS やライブラリと極めて高い親和性を持ち、OS やライブラリ
              の既述言語としても適している。

              また、C 言語の『言語仕様』は不可分な処理を定義していない。
              ここで言う不可分な処理とは、その途中で割り込み処理が入ることを禁止し、連続して
              実行する必要のある処理のことである。
              (不可分な処理の例としては、Stop-the-world型の GC を持つ多くの言語は GC 中に割り
                込みが入らないこと要求される。また、Java においてはオブジェクトの生成などが不可
                分な処理として定義されている。)
              現在の計算機はシグナル・例外による割り込みを利用することが前提となっている。
              これらを言語側でコントロールするためには、不可分処理のない C のような言語が適し
              ている。

              以上の 2 つの理由によって現在の計算機・OS モデルがなくならない限り、C 言語は
              残り続ける。

              また、CPU のローレベルな機械語を既述する必要はこの先もなくならない。
              その時、テキストによって機械語を既述できる『記法』としてアセンブラが残る。」

          p.s.

          C 言語の言語仕様としての最大の特徴はポインタですね。
          ポインタは、、、100年後はなくてもいいや。
          --
          コンタミは発見の母
          親コメント
          • >C 言語の言語仕様としての最大の特徴はポインタですね。
            >ポインタは、、、100年後はなくてもいいや。
             ガンダム0083はデンドロビウムのプログラム。C言語で書かれていて…
             far* なんて書かれてて、見た瞬間にぶっ倒れた(笑)

            #その時代にもセグメントあるのかよー!
            #史実(?)に則ってセグメント残します?>ガンダマーな人たち

            -//-
            親コメント
            • 残すのではなく、すっかり忘れた頃に復活するのです。
              親コメント
            • #その時代にもセグメントあるのかよー!
              セグメント自体は IBM の mainframe にもあったはずですし、8086~286 での実装が (当時のライバルだった 680x0 に比べると) ダサかったというだけで、特に「セグメント方式一般」を否定する理由はないと思います。
              #史実(?)に則ってセグメント残します?>ガンダマーな人たち
              残っててもいいんじゃないですか? 種種雑多な仮想マシンを同居させるつもりなら、セグメントはそう悪くないと思いますけど。
              親コメント
            • >C 言語の言語仕様としての最大の特徴はポインタですね。
              >ポインタは、、、100年後はなくてもいいや。
               ガンダム0083はデンドロビウムのプログラム。C言語で書かれていて…
              あれはC言語ではありません。「G言語」です。
              1024ビットアドレス空間で動いていたザクに対し、連邦は4096ビットチップ動作なのです。
              で、1年戦争終了後にジオン由来の技術者が技術的ギャップを埋めるために、失われた黒歴史からfarポインタを復活させたのです!!

              …とか言ってみるテスト。
              親コメント
          • プログラムは全てユーザプロセスとして動くものばかりではありませんよ。あるOSの元でプログラムが動くと勝手に仮定すると、Cの重要な本質を見失ってしまいます。

            一般的なコンパイラ出力の C 処理系のみを考えても、スタートアップコードを必要とします。これは C 以外のもので書かれていますよね。

            私はとあるRISCの評価中、IPLのためのload addressとentry addressだけをheaderとしてつけたC言語のプログラムを組んだことがあります。cross compilerゆえlibraryどころかstartupすら使えませんでした。それでもmain()をいきなりentry addressとしてきちんと動作しているんです。なので、上述の命題は誤りです。

            OSの設計を変えてもCできちんと動作するプログラムが存在することは、異なるOSでもCが使えること、さらにOSがない環境下ですらもCで書いたプログラム(Cで書いたOSが動くことが何よりの証拠)が動くことで十分証明されています。

            親コメント
            • > 私はとあるriscの評価中、iplのためのload addressとentry addressだけをheaderとしてつけた
              > c言語のプログラムを組んだことがあります。cross compilerゆえlibraryどころかstartupすら
              > 使えませんでした。それでもmain()をいきなりentry addressとしてきちんと動作しているんです。
              > なので、上述の命題は誤りです。
              brake-handle さんの書いたコードが実行される前に、フレームポインタやスタックポインタを
              セットする(スタートアップの代わりを果たす)コードがあったはずですが、、、

              > osの設計を変えてもcできちんと動作するプログラムが存在することは、異なるosでも
              > cが使えること、
              C プログラムの移植性は、言語の仕様といよりは、プログラマーが移植性を考慮して
              がんばっているから、果たせているのだと思います。
              # C 言語は構造体のパディング、Endian 等に対する対策が言語仕様のレベルでまったく
              #ないですし、int型の長さはおろか、char型が 8ビットであることすら決まっていない。。。

              > さらにOSがない環境下ですらもCで書いたプログラム(Cで書いたOSが動
              > くことが何よりの証拠)が動くことで十分証明されています。
              OS のない環境下で C プログラムを動かす場合には、適切なスタートアップが必要です。
              実際、C でコーディングされた UNIX 系 OS は、要所要所でアセンブラやインライン
              アセンブラを必要としています。

              p.s.

              実用上の問題ない話ですが、C では書けないプログラムがあります。
              メモリアドレス番値 0 に対するメモリアクセスです。

              0 は他のポインタ値と聖別されており 何も指さない状態を示すヌル値です。
              アドレスの 0 番とは区別されます。
              ですから、システムに 0 番のメモリが実装されていたとしても、ヌルへの
              代入はなんらかのエラーとすべきです。

              そのため、本当にマジメに仕様を満すと 8086 の割り込みベクタテーブルの
              最初のエントリが埋められないコンパイラが出来てしまいます。
              # そういう実装系はないと思いますが。
              --
              コンタミは発見の母
              親コメント
              • brake-handle さんの書いたコードが実行される前に、フレームポインタやスタックポインタをセットする(スタートアップの代わりを果たす)コードがあったはずですが、、、

                stack pointerの更新にinline assemblerを使えば、残りの部分はCで書くことができます。特にmemory mapped I/Oの場合はそうです。この場合、ROMにCで作ったcodeを焼き、Cの関数をCPUの初期program counterに合わせることすら可能になります。

                実用上の問題ない話ですが、C では書けないプログラムがあります。メモリアドレス番値 0 に対するメモリアクセスです。

                0を使うのもあくまでlibraryの都合です。別に言語仕様がaccessを禁止しているわけではありません(DOSのころは割込ベクタを直接書き換えるために0番地をaccessしていた)。お望みなら、0xffffffffを使ったっていいんです。ただ、それだとaddress spaceの大きさによって値が変わってしまうことや、一部のRISCではalignment errorを起こすために0を選んだのです。

                一見言語仕様に思えるこの実装は、実はエラーの早期発見のためにOSがやっていることなのです(pagingが可能な場合)。

                親コメント
              • 0を使うのもあくまでlibraryの都合です。別に言語仕様がaccessを禁止しているわけではあり ません(DOSのころは割込ベクタを直接書き換えるために0番地をaccessしていた)。お望み なら、0xffffffffを使ったっていいんです。ただ、それだとaddress spaceの大きさによって値が 変わってしまうことや、一部のRISCではalignment errorを起こすために0を選んだのです。
                この情報はどこで聞かれました?

                歴史的経緯はおいておくと、 以下のことは言語仕様によって決まっています。
                • ソースコード上の 0 という文字リテラルはヌルポインタを指すこと(0 が Java の null と同じ扱いを受けている。0xffffffff ではいけない)。
                • 簡便のために NULL マクロを用意すること。その値は 0。
                • ヌルポインタは真偽値として偽を返すこと。その他のポインタは真。
                決まっていないこと。 今、急に思い出せないこと。
                • ヌルポインタへのアクセスに対して どう振る舞うべきなのか
                • ポインタ演算の結果 0 になった場合、どう扱うべきか?

                  ちょっと手元に K&R がないので MSDN ライブラリの「NULLポインタ」の項目を引かせてもらいます(ただし、C++の説明と混じっています)。

                  評価結果が 0 になる整数定数式、または void * 型にキャストされた式は、NULL ポインタと呼ばれるポインタに変換されます。 このポインタは、有効なオブジェクトや関数を指すいかなるポインタと比較しても、等しくならないことが保証されていま す。
                  というわけで、演算結果であろうと 0 になったものはヌル。 ヌルの先に有るのは有効なオブジェクトではないので、 その先へのアクセスは正常ではありません。

                • ヌルポインタ 0 を代入されたレジスタなりメモリの内容がどうあるべきか。

                  これは未定義です。
                  p = 0; とやった時、p の指すレジスタなりメモリの内容は普通 0 ですが、0 である必要はなく 0xffffffff でもいいのです。
                  ただ、0(ヌル) のメモリ表現を 0xffffffff にすると、 言語仕様を破っても アドレス 0 にアクセスできなくなります。

                これ意外にも C 言語には size_t、ptrdiff_t のように 言語仕様に定められた型。 alloca、va_arg/var_start/var_end、setjmp/longjmp のように (ライブラリのみでは実装できないので)言語仕様に 入れておいてくれよと言いたくなるような機能が 放置されております。
                --
                コンタミは発見の母
                親コメント
              • > stack pointerの更新にinline assemblerを使えば、残りの部分は
                > Cで書くことができます。... 合わせることすら可能になります。

                brake-handle の旦那。そりゃもう反則ですだ。
                2つ親のコメントでは移植性の話をしていたし、 この コメント [srad.jp] では、せっかくいいこと書いていたのに
                Cが今まで生き延びてきた、そしてこれからも生き延びていけるであろう本質 は、後から追加が必要になった機能を全てlibraryに押し込めることができるた めです。決して新しい機能のために言語の文法や意味論に手を加え、それゆ えに過去のsourceを捨ててしまうようなことをしなかったのが強く効いています。
                inline assembler なんて言語仕様の横穴を認めるなら、 オラ Java でも OS が書けそうな気がしますだ (IBM の Jalapeno みたく)。

                p.s.
                まじめな話、brake-handle さんが 私の最初のコメント [srad.jp]を読んでどう感じるかが 知りたいです。 個別のポイントではなく、全体として。
                --
                コンタミは発見の母
                親コメント
              • alloca、va_arg/va_start/va_end、setjmp/longjmp のように(ライブラリのみでは実装できないので)言語仕様に入れておいてくれよと言いたくなるような機能

                意味がよく分かりません。libraryに欠けている機能は何ですか? 言語仕様に入れるべき理由は?

                手元にあるFreeBSDのlibcは、allocaもsetjmp/longjmpも実装しています。libraryにしてはいけない理由は見当たりません。同様に、gccだってva_*をきちんと実装しています。

                親コメント
              • 全体に対する感想なぞありません。VBで生成したcodeをUnixの元で走らせることに成功したのですか? 現実にやっていないことを話してもらっては困ります。

                強いて挙げるとすれば、あなたはOSの束縛から逃れることができていないのでしょう。だから私が一切持ち出していないにもかかわらずあなたはOSのABIの話をしたのです。この時点で残りを読む気が全て失せました。

                親コメント
              • 可変引数の関数呼び出しが言語仕様で定められている以上、それを扱う処理も言語仕様内で書けた方がいいのは明らかだと思うのですか如何です?
                また、多くの実装系では va_arg/va_start/va_end はコンパイラによって特殊に処理される擬似関数となっています。単なるライブラリとして書けないものをライブラリの振りをさせるのはまずいでしょう。

                > 手元にあるFreeBSDのlibcは、allocaもsetjmp/longjmpも実装しています。
                > libraryにしてはいけない理由は見当たりません。

                alloca に絞って反論します。
                FreeBSD はalloca 関数を本当に libc だけで処理していますか?
                コンパイラ(gcc)で特殊な処理を入れていませんか?

                少なくとも Linux(x86)上の gcc 2.95.3 では、alloca は擬似関数です。alloca 関数は alloca.h で宣言されたライブラリ関数のように見えますが、実体は違います。

                /* alloca_test.c */
                /* Compile: gcc -S -O0 alloca_test.s
                #include <stdio.h>
                #include <alloca.h>

                void foo(){
                    char* p = (char*)alloca(100);
                }
                出力されたアセンブラファイルからは外部関数の呼び出しが消え、esp レジスタの操作に変わっています。
                私は、このようなコンパイラの支援を要求するものは、ライブラリ関数の範囲から逸脱していると考えています。
                --
                コンタミは発見の母
                親コメント
              • > 強いて挙げるとすれば、あなたはOSの束縛から逃れることができていないのでしょう。
                > だから私が一切持ち出していないにもかかわらずあなたはOSのABIの話をしたのです。
                > この時点で残りを読む気が全て失せました。
                私は無論 OS の束縛から逃れていませんが、それを意識しております。

                逆に私の目には brake-handle さんが、C 言語が ABI に依存している、つまり
                OS やアーキテクチャに束縛されていることに無自覚なように見えます。

                私はとあるRISCの評価中、IPLのためのload addressとentry addressだけをheaderとしてつけたC言語のプログラムを組んだことがあります。cross compilerゆえlibraryどころかstartupすら使えませんでした。それでもmain()をいきなりentry addressとしてきちんと動作しているんです。
                これも、C コンパイラが出力したオブジェクトコードがなぜきちんど動作するのかを考えると、
                ABI の話が出てきますよね?

                > 全体に対する感想なぞありません。VBで生成したcodeをUnixの元で走らせることに成功したの
                > ですか? 現実にやっていないことを話してもらっては困ります。
                本当に私のコメント [srad.jp]を読まずにレスをつけているのですね。
                私のコメントは brake-handle さんのこの [srad.jp]コメントに対するものですよ。
                --
                コンタミは発見の母
                親コメント
              • by pee02674 (7296) on 2002年10月17日 9時30分 (#184665) 日記
                ANSIでは、NULLの定義は(void*)0となっています。が、NULLは抽象概念にすぎず、
                正確には"無効であることが保証される値"です。内部的には処理系依存。
                CPU 0番地が有効な処理系では、内部で違う値を振らなくてはなりません。
                別に有効な値でも、処理系が"そこは無効"とする値でもかまいません。
                MS-Cはデータセグメントの先頭にNULLを割り当てていましたね。

                組み込み系では専用のコンパイラが使われることが多いですが、ANSI標準なんて
                ことはまずありません。最初から、NULLに無効な値を定義することだってあります。

                -//-
                親コメント
              • > CPU 0番地が有効な処理系では、内部で違う値を振らなくてはなりません。
                > 別に有効な値でも、処理系が"そこは無効"とする値でもかまいません。
                > MS-Cはデータセグメントの先頭にNULLを割り当てていましたね

                ですね。
                ただ ソースコード上の `0' の表記と、ナルポインタの内部表現を変えた時に、
                メモリの 0 番値にどうやってアクセスするかは頭をひねらないといけないと思います。

                フラットなメモリ空間を持つシステムで実装を行なうなら、
                pointer の内容がメモリアドレスから定数オフセット分ずれていると
                するとオーバーヘッドが小さいかしら?

                    (ポインタの内容) = (メモリアドレス) - (仮想記憶のページサイズ; 例えば 4K)

                としておいて、

                    int* p;
                    p = (int*)4096;
                    *p = 0 ; // メモリ 0 番への書き込み

                    p = 0;
                    *p = 0 ; // これはヌルポインタへのアクセス。
                --
                コンタミは発見の母
                親コメント
          • brake-handle さんと話が噛み合わないなあと、考えていて気づいたのですが、
            C 言語には static な記憶クラスを持つ変数(global、static変数)は初期化が
            必要であるという言語仕様上の規約があります。

            普通の OS ではリンカとローダーにお委せしてしまうので実行していると気がしませんが、
            これは関数実行前に済ませる必要のある初期化処理です。
            今、この処理をローダーまかせにしないプログラムを書いているせいか、初期化処理を
            前処理のうちに数えないの個人的にはすごく違和感があるのですが、皆さんはどうですか?
            (C++ の場合なら、コンストラクタを順に呼び出す必要があるので強く意識すると思う。)

            実際には、コード部分を ROM に焼き付けてしまう組み込み系や、実行の途中で
            動的にロードされる共有ライブラリなどで問題になってくると思うのですが。
            --
            コンタミは発見の母
            親コメント
        • Lispマシンがなくなったように(?)バイトマシンがあと100年残る気は、僕はしません。

          # そんだけ。
          親コメント
        • by G7 (3009) on 2002年10月15日 23時44分 (#183917)
          他の方も指摘してますが、Cとアセンブラとは、その文脈の意味において(も)、一緒にならないと思います。

          アセンブラは今風の延長のCPUがありつづける限り、その「後釜言語」が出現するってことを
          考える意味が無いはずなので、そういう意味では未来永劫残るでしょう。

          でもCは、後釜言語が出現するかも知れない。
          30年後の俺らの後輩?は、今のCと似ているような似てないような後釜言語を
          (そういう用途に)使っているかも知れない。

          もちろんこれは、たまたま惰性でCが今のまま使われ続ける可能性を否定するものではありません。
          ただ、残るにせよ残らないにせよ、それは「たまたま」であって、アセンブラのそれとは違って必然では無い、とは言えると思います。

          だから、「アセンブラと、Cのような中級言語と」が残る、という説ならまだなんとなく納得がいきます。

          もっとも、未来における中級言語のメジャーな位置付け自体が、上か下のどっちかにシフトしてしまう可能性も
          ないわけではないでしょうから、後釜がCに十分(?)似てるという保証すら、必ずしも無いのですが。

          なお、Schemeの実装におけるスタックフレーム [dreamhost.com] あたりを読んでいると、
          Cの(メジャーな(と言っていいですか?俺ぁ疎いもんで御免))実装の Stackの使い方とかは、
          色々考えられる実装形態のうちの1つでしかなくて、それ以外の実装
          (たとえばこの例ではScheme寄りの)を支援しないものに過ぎない、のだなと思っちゃいます。
          つーか、そのとおりですよね?
          そういう意味では、そのCの限界を超えられる言語は常に必要であり、それがアセンブラだったり
          アセンブラとCの間くらいの高級度のなんらかの言語だったり、するのだろうと思います。

          >もっとも、アセンブラがどういう言語かという問題は残りますが、LispマシンだったらLispがアセンブラのようなものですしね。

          うーん。そうなんだろうか?
          Luspマシンって、ユーザプログラミングのために提供された(隠されなかった)部分の高級度が、 Lispのソレであるわけですよね。
          アセンブラというノリじゃないような気がします。
          むしろ大昔のパソコン(^^;でいうROM BASICに近い位置付だったりしませんかね?
          もちろん言語の出来が違いすぎるんで、BASICとLispでは色々な面で比較にならないでしょうけど、ね。
          親コメント
          • by USH (8040) on 2002年10月16日 0時31分 (#183946) 日記

            Luspマシンって、ユーザプログラミングのために提供された(隠されなかった)部分の高級度が、 Lispのソレであるわけですよね。
            アセンブラというノリじゃないような気がします。
            むしろ大昔のパソコン(^^;でいうROM BASICに近い位置付だったりしませんかね?
            もちろん言語の出来が違いすぎるんで、BASICとLispでは色々な面で比較にならないでしょうけど、ね。

            Lisp マシンというのは、CPU の設計からすでに LISP 向きに設計されているものをさすのだと思います。例えば、あらゆるメモリにはかならずタグがついており、car や cdr など基本関数はハードウェアで実装。GCもマイクロコードでやったりとか。少なくともいまはなき Symbolics Machine という Lisp マシンは、アセンブラコードがかなり Lisp に近いもので、car, cdr, cons とかに相当するものが並んでました。
            親コメント
          • なんだか、CとASMは生き残るって話から逸れて行ってるような気がしますが…
            Cが生き残るのは「低機能で実装が簡単」だからで、機能が足らないから
            廃れるってのは逆方向ではないですか?
            リンク先読みましたが、組み込み系で多用されているZ80の発展型にガベコレを
            実装した環境ってあるのでしょうか?Cに比べて実行時の要求リソースがかなり
            大きいと思いますが。実装依存と書いてあるから、Cに匹敵する少リソースでの
            実装形態もあるのかもしれませんが。
            #Schemeは初めてかじったので、理解が浅い点はご容赦ください。

            あっと、100年後の話でしたね。100年後でも、消費電力の関係やサイズの関係で
            強力なCPUを採用できないとか、コストをギリギリまで削る必要のある用途では
            低速低機能なCPUの用途は無くならないと思います。そもそもZ80程度の能力で
            済んでしまうというような用途も無くならないでしょう。低機能CPUの需要が
            無くならない限りは、低機能なC言語の需要も無くならないでしょう。

            -//-
            親コメント
            • > 組み込み系で多用されているZ80の発展型にガベコレを
              > 実装した環境ってあるのでしょうか?

              CP/M-80上で動くLispはありましたね。Prologも。APLも。
              昔、TIかどっかで作ってた、PC-Schemeでしたっけ、直接
              機械語に落す処理系があったと思うんですが、あれは
              ターゲットプロセッサは何だったかな。

              最近のものでマイクロコントローラ向けに書かれたものとしては
              Bitとか。http://www.iro.umontreal.ca/~dube/ から論文への
              リンクがあります。68HC11とかで走らせることを念頭に置いて
              いるとか。ただ、実装はCで素直に書かれたVMのようです。
              親コメント
            • いや、Cに機能が足りないからどうこう、という話を
              (俺が)しようとしたわけじゃないですし、
              恐れ多くもZ80様を忘れようと思っているわけでもありませんm(__)m

              StackFrameの話ですが、StackFrameの1種類の使い方しか提供されなくて
              変更不能(それを変更することはC自身の領分を超える)ということは、
              都合(それこそ処理効率とか)に合わせて色々なStackFrameの使い方を
              使い分けるということが出来ない、ということですよね。
              ということは、もしそれが可能な(C似かも知れない)言語があったら、Cは
              (組み込み用途でも)負ける、のではないか?とは思いました。

              Closureだの継続だのを持ち込みたい(それが贅沢であるのか否かという議論は
              ここではしません。つーか俺もまだ全然理解してないので回避)とまで
              言わずとも、もっと安直なところで、関数呼び出しの処で、どうStack(とレジスタ)を
              使うことにするか、なんてな問題も有りますよね。
              ああいう処って、特に小さいCPUでは、きめ細かく使い分けたくなるものでは無いのでしょうか?

              それとも、StackFrameの使い方を使い分ける、なんていうニーズは
              組み込み方面にも無い、ということなのでしょうか?
              いや、それは(素人には)考えにくいなあ。玄人考えでは考えやすいことなのでしょうか?(^^;

              そりゃそうと、むしろCPUのほうが「Cに都合の良いように」作られてる、ってことは無いでしょうか?
              Cの言語仕様に素直に馴染むような命令ばかりを強化しがち、というような…?
              これだけCが(特定のCPUのブランドなんかより(^^;遥かに)メジャーになってしまえば、
              そういう歩みよりが生じても不思議は無いっすよね。

              >組み込み系で多用されているZ80の発展型にガベコレを
              >実装した環境ってあるのでしょうか?Cに比べて実行時の要求リソースがかなり
              >大きいと思いますが。

              べつにSchemeを実装しろとかいうつもりは無いです。
              「あーいう(どーいうのでもいいんだけど、とにかくCとは違う)Stackの使い方」
              をするような何かを実装したくなることは無いですか?という話をしたかったのであって。

              それとももしかして、「1つのCPUではStackの使い方は多様である必要は無い」と実用的に言えるのでしょうか?
              それならば、そのCPU用にCコンパイラを1つ移植すれば(その際にStackの使い方を1つ授ければ)
              済むことだ、といえるようにはなりますが、そういうことなのですか?
              親コメント
              • > そりゃそうと、むしろCPUのほうが「Cに都合の良いように」作られてる、ってことは無いでしょうか?
                > Cの言語仕様に素直に馴染むような命令ばかりを強化しがち、というような…?
                > これだけCが(特定のCPUのブランドなんかより(^^;遥かに)メジャーになってしまえば、
                > そういう歩みよりが生じても不思議は無いっすよね。

                パソコン、ワークステーション向けのプロセッサは C 言語がターゲットです。
                というよりも、もっと狭くてSPEC CPU ベンチマーク [spec.org]を基準にして
                いると言ってもいいと思います(ちょっと言い過ぎかも)。

                SPEC cpu は整数系が C (少しC++)、浮動小数点系が FORTRAN 75/90(少し C) で書かれています。
                プロセッサ設計の最上流では、SPEC cpu ベンチマークを既存プロセッサで走らせた命令トレースを
                手に入れ、その中に出てくる命令頻度、メモリアクセスパターン、キャッシュの挙動を調べ、新しい
                機能を考案してゆきます。で、新しいプロセッサのパイプライン・機能ユニットを模したクロック
                シミュレータで評価を行うのも SPEC cpu の命令トレース/バイナリです。
                # 他所のことは、よく知らんのですが、、、

                で、そんなことをやっていますから、C 言語のレベルでは書けない命令(ローテート命令とか)は
                どうしてもおざなりになります。
                例えば、レジスタ中の 1 が立っているビット数を数える population 命令が、Alpha や POWER 系には
                実装されており、ビットを使った集合演算をやろうとすると非常に重宝します。
                SPARC の命令セットにもこの命令はあるのですが、UltraSPARC III では実装していません。
                Solaris が population を実行すると不正命令例外が発生するので、それをトラップしてソフトウェア
                処理します。トホホ。
                --
                コンタミは発見の母
                親コメント
              • >>#184563 [srad.jp]

                わたしも玄人なんておこがましいこと言えるようなもんじゃないです。
                そんなこと言ったら、本物の玄人が裸足で逃げだしてしまいます。

                私にはStackFrameを使い分けるという概念がありません。
                だから、どんなメリットがあるのかも理解できません。
                よければ例を示していただけると。ポインタでもかまいませんので。

                CPUがCに都合よくというのは歴史的には賛成できませんが
                現実的に、基幹部がCで開発されることが主流である以上
                あり得ない話ではないと思います。もっとも、基幹部のCに
                高級アセンブラ以上の意味があるとは思えませんが。

                「1つのCPUではStackの使い方は多様である必要は無い」
                1つのCPUに、多様なStackの使い方が実装されている例があれば。
                私はStack Lineを複数持つCPUは知っていますが、
                Stack Frameの使われ方が複数あるCPUは知りません。
                ところで、Cのいいところはアセンブラとの直交性です。
                直交性の確保できない処理系で、Cを採用する必要はないと思います。

                -//-
                親コメント
              • スタックフレームの使いわけとして1番有名なのは、 プロシージャ(関数)のC規約呼び出しとPASCAL規約呼び出しの違いでしょう。 前者は呼び出し元(caller)がフレームの解放を行ない、 後者は呼び出し先(callee)がフレームの解放を行ないます。

                C規約呼び出しの利点は caller が完全にフレームを制御するので、 可変長引数などが実現可能な点。複数の関数呼び出しが連続するとき フレームの解放をさぼれる点でしょう。

                PASCAL規約呼び出しの利点の方は現在では認識し難たいですが、 以下のようなストーリーがあります。
                RISC アーキにとってスタックレジスタ(sp) は汎用レジスタの 1本にすぎません。 しかし、CISC アーキにとって、sp は push / pop など命令と結び付く特別なレジスタでした。
                CISC のリターン命令の中には、 RISC でいうところの return 命令と sp 操作を同時に行う効果を持つものがあり、 この命令を使える分callee 側でのフレーム解放は効率が良かったのです。

                OS によっては 2つの呼び出し規約は現代でも混在しています。
                UNIX が C 言語で記述されたように、 初代 Mac OS は Pascal で記述されました。
                その名残で Mac OS の API は PASCAL規約の呼び出しルールを持っています。 Windows も同様です(本当は __stdcall)。

                C規約の関数呼び出しは C 言語自体の仕様ではないですが、 非常に一般化しています。 そのため、 Window や Mac の C 処理系では、 OS のシステムコールを直接呼び出したり、OS に渡すコールバック関数を作ることなどが、言語の範囲内ではできません (無論、処理系独自の拡張で凌いでいます)。


                p.s.
                PASCAL規約が残っているのは、歴史的な理由が多いので、これをスタックフレームの使い分けの例として出すと、ご不満かもしれません。
                もう少し効果のあるスタックフレームの使い分けてとしては、 コンパイラの関数間最適化による register promotion を挙げておきます。
                --
                コンタミは発見の母
                親コメント
              • >PASCAL規約呼び出しの利点の方は現在では認識し難たいですが、以下のようなストーリーがあります。

                以前どっかで聞いたような気がしますが、Pascal呼び出しだと、Stack後始末をするコードを持つ個所が、
                「呼び出す側」じゃなく「呼び出される側」になることによって、その「数」が減る、という話だったような。

                それ以外の例としては、やっぱり、Schemeの実装におけるスタックフレーム [dreamhost.com]あたりが参考になる、んでしょうか。
                特に
                >但し、現存するScheme処理系の多くはベースにC言語を用いており、このような特殊な スタック操作が実装しにくくなっています。
                という辺りが、
                Cと違うStackの使い方が欲しくなることが(こういう風に)有るのを物語っているんじゃないかと。

                まあScheme(Lisp系)なので、「関数」という概念の定義自体がCのそれとは微妙に違う
                (ルーチンおよびそれに直接従属する"状態"しか持たないCの関数に対し、
                Lispの関数はルーチンに従属せずヨソからアクセスも可能な"状態"を持つことが出来るらしい。
                つーかこれがClosureとかいう奴ことらしい。そういう考え方を導入するメリットについては
                それこそそっちの頁とかを読んで下さい。俺もAuto変数とStatic変数だけじゃウンザリするのは十分経験済み)
                ので、CのStackFrameとがらっと違うStackFrameが(効率を上げるために)要求されるのは、当然なんでしょうけどね。
                親コメント
        • せっかくの興味深い議論だと思うので、なるべくなら収束させた方が良いと思うのですが。

          その意味で役に立つかどうかわかりませんが、アセンブラとCについての私の意見です。多くの項目が既出ですが、ご勘弁を。結論はbrake-handleさんの元コメント [srad.jp]と同じです。

          アセンブラは、#183921 [srad.jp]で既に述べた通り、ノイマン型コンピュータの最下層のソフトウェアです。ノイマン型が存在する限りアセンブラはなくならないでしょう。

          ただし、アセンブラをプログラミングで直接使うことは稀です。機種依存性が高く構文が貧弱なため、開発効率が低いからです。アセンブラで記述しなければならない状況の例として、特権命令等の特殊機械語命令を書く時、スタックポインタなど特定のレジスタにアクセスしなければならない時などがあります。また、アセンブラで記述した方が望ましい状況の例として、スタックポインタなどコンパイラが自動で使用するレジスタ変数が初期化されていない時(例えばIPL)などがあります。

          アセンブラの主用途はコンパイラのバックエンドであり、言語としては「裏で生き続ける」という感じでしょうか。

          Cは、「すべての構文要素が、単体で動作する機械語列に変換される」という特徴を持ちます。これがCの最大の利点です。OSやサポートライブラリが関与する操作は構文内には存在しません。OSが関与する多くのOSに共通する機能・一般的に便利な機能は、標準ライブラリとして構文とは独立に定義されています。この(そのまま機械語になるという)利点があるため、他の高級言語ではほとんど真似のできない、OSを記述すること・OSが存在しない状況で動作するプログラムを書くことなどが可能です(ただしC++でも可能ですよ)。

          Cまたはアセンブラで記述できる状況であれば、より機種独立性の高いCを選択する方が合理的です。したがって、現在のCの地位を奪うものが現れない限り、Cは生き続けるでしょう。また、Cのほぼ上位互換言語でさらに付加機能も持っているC++が、今のところCを置き換えることに成功していないことから想像して、Cを駆逐する言語は現れ得ないように思います。アセンブラの生存理由と違ってこちらは明確な根拠じゃないですけどね。

          以上の理由から、アセンブラとCはどちらも長い寿命を持つ、と思います。
          # 細部はともかくとして、基本的には元々こういう話じゃないか
          # と思っていましたがどうでしょう > brake-handleさん
          親コメント
        • Cとアセンブラの話じゃないですし、Cの生存性のおおもとの論旨に反対するわけでもないのですが、C++についていくつか指摘しておきます。
          # 読んでいる方に誤解があるといけないので

          メモリアロケータが構文に組み込まれている点について。newとdeleteは演算子であり構文のひとつですが、演算子オーバロードによりユーザ定義関数呼び出しに置き換えることができます。大域的newもクラスごとのnewも再定義できます。deleteも同様です。したがってnewとdeleteが演算子として存在することは、実行時性能の観点ではCの標準ライブラリでmallocやfreeが定義されていることとたいした違いがありません。また、C++そのものがnewを多用することを要求しているわけではないため、newが存在することが言語のデメリットとはなりません。

          オブジェクト指向について。話が発散気味なので私の指摘の意図が的を射るかどうかわかりませんが... もし「組み込み用途にはオブジェクト指向は邪魔だし不要だ」という意見であれば、それは使用者次第だと思いますよ。仮想関数などの動的な機能を多用すれば確かに性能面で邪魔ですが、それは動作環境に適したコーディングをしていないだけです。カプセル化、情報隠蔽、継承などは(ムチャな使い方をしなければ)実行時性能に影響を及ぼすものではなく、用途を考えつつ正しく使えば開発効率上の利点を得ることができます。インライン関数という性能面での補助もありますしね。

          これらのご指摘は、おおむね「C++がCよりも多くの機能を持っている」という点を否定的に見ているものかと思います(違ったらごめんなさい)。が、機能が存在することと機能を使うことは別問題です。用途に応じて種類や使用方法を使い分けるのが言語の正しい使い方であり、特にCやC++を実装言語に選んだ場合には、用途に適した使用方法が暗黙のうちに要求されるように思います。例えばnewについて、「C++にはnewがある。newを使うのがC++の標準的なやり方だ。newを多用したプログラムは組み込みに向かない。だからC++は組み込みに向かない」という論法は、誤りです。組み込み用途向けのコードでnewを多発するのは、使用者の使い方が誤っているだけでC++が誤っているわけではありません。

          ただし、「C++がCよりも多くの機能を持っていて、使わなければ悪影響はない。だからC++はCと同じだけ生存し続ける」という論法もまた、成り立たないですね。付加機能が多くの人にとって要らないものと見なされれば、飽きられて廃れていくと思います。現状でも「どうにも必須の言語」ではないでしょうし。
          # 私自身はC++の機能群はほしいと思っていますが
          親コメント
          • すみません。「メモリアロケータが構文に組み込まれている点について」のところ、何だかちぐはぐですね。主張したかったのは、
            • 組み込み用途でnewを多用するのはそもそも使い方が誤っている。C++はnewの使用を強制してはいない
            • newとdeleteは再定義できる。だからnewとdeleteを使ったからといって標準のメモリアロケータを強制されるわけではない
            • 組み込み用途でもnewを使い、なおかつ独自のメモリ管理もしたいのなら、がんばってnewとdeleteを再定義すればよい(それが適切な結果になるかどうかは使用者次第だが)
            ということでした。失礼しました...
            親コメント
        • 結局、brake-handleさんの言ってる事って、「Cは高級アセンブラであるが他の言語はそうではない」と言っているだけなんですね。
          組み込み屋さん/OS屋さんの見地から「生き残るのはC=アセンブラ=マシン語=ハードウェアだ」と言ってるわけで、そりゃ当たり前だよね。

          #…という文脈を理解できなかったので、なぜにLispマシンが出てくるのかさっぱり分からなかった

          で、言語屋とかアプリ屋とか、抽象度が上がった世界を中心に据えて議論している人とはまーったく話がかみ合ってない、と。
          親コメント

アレゲは一日にしてならず -- アレゲ見習い

処理中...