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

MSが大学に寄付してC#が必修科目に」記事へのコメント

  • by Anonymous Coward
    今更C言語覚えるより良いのかもね。
    ポインタバリバリ使ってバギーなコード書かれるよりはましかも。
    卒業したらJavaに移行して貰えばいいし。

    でもコンピュータサイエンティストなら、アセンブラはやって欲しいけどね。
    • Re:いい方に考えると (スコア:1, すばらしい洞察)

      >ポインタバリバリ使ってバギーなコード書かれるよりはましかも。

      でも、同じ問題は結局JavaだのRubyだのでも生じますよね。ポインタつーか参照については。
      単に症状の出方が違う(いきなりコアダンプするか、NullPointerなんたらExceptionが出るか、の違いというか)だけで。

      ポインタって、その概念的原理(つまり、なにかがなにかを「参照」する)と、 C独特の構文と、
      の2者さえ理解すれば、逆にいえばたいして難関でもないと思います。
      あの程度のことを理解*できない*ような人ならば、情報系の学生だろうが仕事だろうが趣味(フリーソフトとか)だろうが
      こっちとしてはちょっと
      • 「ポインタ」と「参照」は異なる機構ですよ。
        「ポインタ」は「参照」としても利用できるように設計されていますが、「参照」よりも遥かに広いポテンシャルを持った機構です。ゆえにバグの温床となる。

        「ポインタ」はメモリアドレスを示す「値」(+型情報)、「参照」はもっと抽象的なオブジェクトやクラスなどを参照することができるデータ。

        例えば、言語屋さんから見ると C 言語には "call by reference" がないように見えるそうです。C 言語が "call by reference" と称しているのは、アドレスを渡す "call by value"。

        > でも、同じ問題は結局JavaだのRubyだのでも生じますよね。
        --
        コンタミは発見の母
        • >例えば、言語屋さんから見ると C 言語には "call by reference" がないように見えるそうです。C 言語が "call by reference"
          >と称しているのは、アドレスを渡す "call by value"。

          C言語の文法と挙動を正確に理解できるようになるために学ぶ段階において、
          C言語がcall by referenceだなんて考えたらドツボにはまっちゃうわけで。

          あくまでcall by valueと考えるべき。

          そう考えることで、初学者にもベテランにも言語屋さんにも、誰にとっても
          矛盾なく使える(かつ、なにか重要なものを欠落させるわけでもない)モデルが
          頭ん中に構築できるわけで。

          言語屋さんには見える、
          • > CのポインタとJavaとかの参照との違いとして、「データじゃなく変数(データの器)を」指すということ
            > が可能か不可能か、という差がありますね。 他の変数に代入されてる値にアクセスする、ということ
            > が、この機能の有無によって、可能か不可能か変わってくる。
            >
            > でも逆にいえば、それしか差は無いわけで。

            それしか、、、ですか。
            私はコンパイラ屋で GC 屋ですから、この 2 つの間に 言語のポテンシャルを完全に
            左右する違いを見ているのですが、、、

            > あ。ごめん。もうひとつだけ差があった。Cのポインタには「演算」が定義されてる。
            > ++とかが出来てしまう
            --
            コンタミは発見の母
            • C++ の「参照」が、「ポインタ'」にすぎないという点には同意。
              同意できないぞ。参照型ではアドレス演算できない。参照先を変更できない。

              誰でもいいけど、C++の参照がJava等の参照と異なると言うなら異なる点を列挙せよ。

              • > 同意できないぞ。参照型ではアドレス演算できない。参照先を変更できない。

                ちょっと工夫すると、参照型とポインタは交換可能です。

                #include <stdio.h>

                int goo( int& a, int& b ){
                    // a b が実体を参照しているとは限らない
                    printf("a=%d, b=%d\n", a, b );
                }

                int main(int argc, char** argv){
                    int a=0, b =1;

                    goo(a,b);
                    (*(int (*)(int*, int*))goo)(&a, &b);
                   
                --
                コンタミは発見の母
              • おいおい。それは参照がポインタになるんでなくて、ポインタを悪用してるだけだよ。濡れ衣だ。
              • 訂正: ポインタのみならずキャストをも悪用してるだけか。 何れにしても濡れ衣だよ。 C++参照が他言語の参照と違うという例にはなってない。

                一旦参照型変数を初期化したオブジェクトを、他のオブジェクトに置き換えれるようなら、(参照というよりは)ポインタ的と言えるだろうけどそれはできないでしょ?

                Foo foo1, foo2;

                Foo *p = &foo1;
                // ポインタなら

              • 他の言語の「参照」が持つ consistency が、C++ の参照型は実現できていない点が問題なのです。
                その証拠に、ポインタが原因となって発生するバグのほとんどが、参照型でも発生するでしょう?

                無論、C++ がポインタやキャストを禁止すれば、参照型は「ほぼ」参照となりえますが、現実的にこれらの機構はある。
                さらに言えば、実装的には参照型はポインタに皮を被せているだけでしょう。

                > 一旦参照型変数を初期化したオブジェクトを、他のオブジェクトに置き換えれるようなら、
                > (参照というよりは)ポインタ的と言えるだろうけどそれはできないでしょ?
                別に指し直せないことが「参照」の要
                --
                コンタミは発見の母
              • 「参照型のインスタンスが別のオブジェクトを指し直す危険」以前に「局所変数へのリファレンスを関数が返すという過ち」に基づいてますが、実現できるという点で納得です。

                現実にこのような過ちを繰り返している人がいるとすればそのことに驚きですが(何故なら通常コンパイラの警告で除去できるミスなので)、まぁいるんでしょう。

              • > 現実にこのような過ちを繰り返している人がいるとすればそのことに驚きですが
                > (何故なら通常コンパイラの警告で除去できるミスなので)、まぁいるんでしょう。

                おお!これは私に対する挑戦ですね。いいでしょう。
                警告を出させずにローカル変数の参照を運び出してみせましょう。

                ◎ パターン1

                int& foo(int& i) {
                    return i;
                }

                int& goo() {
                    int i;
                    return foo(i);
                }

                まぁ、このぐらいならコンパイラの警告なしでも気づきますよね。

                ◎ パターン2
                パターン1 の応用です。

                class Sample1 {
                    int& index;
                public:
                    Sample1(int& i) : index(i) {}
                };

                Sample1* moo() {
                    int i=0;
                    return new Sample1(i);
                }

                ◎ パターン 3
                暗黙の型変換を使います。

                class Sample2 {
                    int& index;
                public:
                    Sample2(int& i) : index(i) {}
                };

                Sample2 boo(int i) {
                    return i;
                }

                どうでしょう?
                --
                コンタミは発見の母
                親コメント
              • 素直に参りました。こんなの思いつかなかったなぁ。

                でもこれ本気で書いてる人は(前回の例と同様)スタックフレームをまったく理解してないのでしょうね。

弘法筆を選ばず、アレゲはキーボードを選ぶ -- アレゲ研究家

処理中...