アカウント名:
パスワード:
本質的に問題を生んでいるものだけではなく、たんに書いた人が使い慣れている他の言語と違う挙動をするだけ、というものが結構混ざっているような。
私にわかる分だけでも。
>Pythonでインデントレベルがブロックを示すこと
Python全否定されているんだが。CoffeeScriptはいいのか?
>Cの配列インデックスがポインターの算術演算のような動作をすること
他にどうやって配列の中身を表せと。1[a]と書けるとかの話をしている?
>Rubyで「0」がTRUEと評価されること
「0」がfalse出なければいけない理由がC出そうだという以外思いつかないのだが、何かあるのだろうが。
>JavaScriptで勝手に挿入されるセミコロン
Rubyでもそれはなかったっけ?
>Cの配列インデックスがポインターの算術演算のような動作をすること 他にどうやって配列の中身を表せと。 1[a]と書けるとかの話をしている?
うん、元記事ではそういう話をしている。
記事の著者が、どうしてそれでプログラマーが悩まされると思ったのかは知らない。それでプログラマーが悩まされる状況なんて、国際難読 C コードコンテストの応募作品が読解できなくて悩んでいるという状況しか僕には想像できないけど。
"0123456789ABCDEF"[c] とかって書いてあるコードなら見たことある。配列とポインタの関係を知らないと、なぜ問題ないか理解できないとは思う。
c["0123456789ABCDEF"] と書いてあったならともかく、"0123456789ABCDEF"[c] なら問題ないんじゃないかな。
そもそも、ポインタのないC#なんかでも同じ書き方ができますし。すごく直観的なコードでしょう。
C#はunsafe指定でポインタ使えるけど……。
でっかい画像処理の時とか、ポインタ使うと処理が高速化されるケースがあったりする。
Rubyは改行とセミコロンがどちらも文の区切りになるだけで、セミコロンを補うわけではない。JavaScriptのように改行で文が分かれたり分かれなかったりという理解に苦しむ挙動をすることはない。
いや、Rubyは、文の途中で改行していると判断できるときは、改行で分がわかれないこともありますよ。
JavaScriptに比べて慎重に設計してあるので、理解に苦しむことは少ないというのならわかりますが。
改行によって分がわかれたり分かれなかったり、はします。
例えば、
puts 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10
と、
で挙動が違うのは、慣れないと混乱する人もいるでしょう。
RubyでもJavaScriptでも改行の次の行を見ないと分かれるのかわからないのは同じだし、逆に言えば次の行を見れば分かる。
Rubyで次の行を見ないといけないのはどんな時ですか?
たしかRuby 1.9くらいからこういう風に改行を入れられるようになりました。これで、obj.hoge.piyo.foo.barと同じように動きます。
obj.hoge .piyo .foo .bar
この例のように、メソッドチェーンが長く連なると改行を入れたくなることがあります。
Cの配列インデックスってsyntax sugarと思っていなくて、本当に配列というものが存在しているかのように誤解しているんじゃなかろうか。関数の仮引数を配列形の書き方をしている人をみるとそういう気がする。
逆に、ポインタと配列が同じなんて誰が言ったんだ、と憤慨している文章を見たことがあります。
メモリの確保の仕方が全然違うだろうと。確かにその辺は全然違いますね。
プログラミング言語なんてものは概念の世界のものなのだから、どれが本当に存在しているかなんて議論は、そもそも不毛なのかもしれませんね。
void foo(char *a){ char b[3];}
の、bは「本当に存在する配列」と違いますか?
スタックに積まれる物は、aは、「何かのアドレス」が1個だけ。bは、「b[0]」、「b[1]」、「b[2]」に相当する3つのcharになりますよ。
翻訳後の機械語の動作としても、別物になり、
x = *a; // 「スタックポインタ+コンパイル時に決まるaのオフセット(定数)」を計算→その番地の値を読み込む→その番地の値を読み込んで、xに代入x = *b; // 「スタックポインタ+コンパイル時に決まるbのオフセット(定数)」を計算→その番地の値を読み込んで、xに代入// a[0]、b[0]と書いても同様
そんなことをいったら、a だってインライン展開の具合次第でなくなることはあるでしょう。あんまり本質的な議論だとは思えません。まさに、C Languageが「未定義」という必殺技を繰り出す最大の理由でしょう。C99とかではかなり論調が変わってきたのも事実ですが・・・。
いえ、aは、a++できますが、bは、b++できません。配列とポインタの本質的な違いです。
char *a = "abc";char b[]="abc";
も本質的に違い、どちらにも異なる利点・欠点があります。
未定義動作と話が繋がるのかは想像できませんでしたので説明いただけると助かります。
私が、言ったのは、
> bがスタック上のどこにあるのかをコンパイラは把握出来るので、出力する機械語にその値を直接埋め込んでしまえますから、> 実行時に、「変数b」に該当するような値を覚えておく必要、メモリは不要になります。
という部分に対して、bが変数として保存される必要がないという部分に対してです。話が分かりにくくて済みません。
一方で、
> いえ、aは、a++できますが、bは、b++できません。配列とポインタの本質的な違いです。
と言われると、C++プログラマとしては、
char const * const a = "abc";
なんていうヒネクレタ事も言いたくなる部分ではあります。
個人的には、sizeofの挙動以外、大した差ではないと思っていますが。
char *p, a[1];a[0] = 0; /* OK */p[0] = 0; /* NG */
これで大した差がないと?
いや、まじめに「配列とポインタには本質的な違いがある」という人に、このaはポインタなのか配列なのかを伺いたい。形式的にはポインタだしsizeof(a)もポインタのサイズを返すが、性質としては配列というわけでしょう?
大した差ではないな。ケアレスミスを起こすかどうかって本質的な問題じゃないでしょ。
え、まさか配列とポインタの違いも分からないの?
それが大した差でないというなら、sizeofの挙動の違い(に起因するミス)だってケアレスミスであり本質的な問題じゃないです。
"配列"といった場合、そのデータの塊を1つとして扱いたいという意味もあります。ここで sub_func(a), sub_func(b)とした場合、sub_func側で受けとるのは「何かのアドレス」aか,b[0]のアドレスかの違いでしかなく、配列の大きさの情報も,どういった領域のメモリかも受け渡しされません。"b"という識別子だけで、b[0],b[1],b[2]に相当する3つの
JavaScriptのArrayはただのオブジェクト、連想配列と言ったところで仕方ないもんな。
>Cの配列インデックスがポインターの算術演算のような動作をすることa[1]を*(a + 1)の糖衣構文と説明せず、配列同じですよと説明している本が多いから混乱する
配列でも*(a + 1)の糖衣構文なことは同じなので、配列と同じなのは確かではなかろうか?
> Python全否定されているんだが。CoffeeScriptはいいのか?
そもそもCoffeeScriptとか知らない
pythonからインデント取ったらなにものこらないし、何じゃこりゃとしか。PHPのケースセンシティブも少なくともその機能が作られたとき必要なもので、まだi18nの概念が一般化する前とか考えたらそんなもんだし。javaやjavascriptも実装依存に近い性格の癖だったり、その他も一緒かと。
より多くのコメントがこの議論にあるかもしれませんが、JavaScriptが有効ではない環境を使用している場合、クラシックなコメントシステム(D1)に設定を変更する必要があります。
目玉の数さえ十分あれば、どんなバグも深刻ではない -- Eric Raymond
とりとめがないな (スコア:1)
本質的に問題を生んでいるものだけではなく、
たんに書いた人が使い慣れている他の言語と違う挙動をするだけ、
というものが結構混ざっているような。
私にわかる分だけでも。
>Pythonでインデントレベルがブロックを示すこと
Python全否定されているんだが。CoffeeScriptはいいのか?
>Cの配列インデックスがポインターの算術演算のような動作をすること
他にどうやって配列の中身を表せと。
1[a]と書けるとかの話をしている?
>Rubyで「0」がTRUEと評価されること
「0」がfalse出なければいけない理由がC出そうだという以外思いつかないのだが、何かあるのだろうが。
>JavaScriptで勝手に挿入されるセミコロン
Rubyでもそれはなかったっけ?
Re:とりとめがないな (スコア:2)
うん、元記事ではそういう話をしている。
記事の著者が、どうしてそれでプログラマーが悩まされると思ったのかは知らない。それでプログラマーが悩まされる状況なんて、国際難読 C コードコンテストの応募作品が読解できなくて悩んでいるという状況しか僕には想像できないけど。
Re: (スコア:0)
"0123456789ABCDEF"[c] とかって書いてあるコードなら見たことある。配列とポインタの関係を知らないと、なぜ問題ないか理解できないとは思う。
Re: (スコア:0)
c["0123456789ABCDEF"] と書いてあったならともかく、
"0123456789ABCDEF"[c] なら問題ないんじゃないかな。
そもそも、ポインタのないC#なんかでも同じ書き方ができますし。
すごく直観的なコードでしょう。
Re: (スコア:0)
C#はunsafe指定でポインタ使えるけど……。
でっかい画像処理の時とか、ポインタ使うと処理が高速化されるケースがあったりする。
Re: (スコア:0)
Rubyは改行とセミコロンがどちらも文の区切りになるだけで、セミコロンを補うわけではない。
JavaScriptのように改行で文が分かれたり分かれなかったりという理解に苦しむ挙動をすることはない。
Re:とりとめがないな (スコア:1)
いや、Rubyは、
文の途中で改行していると判断できるときは、
改行で分がわかれないこともありますよ。
JavaScriptに比べて慎重に設計してあるので、
理解に苦しむことは少ないというのならわかりますが。
改行によって分がわかれたり分かれなかったり、はします。
例えば、
puts 1 + 2 + 3 + 4 + 5 +
6 + 7 + 8 + 9 + 10
と、
puts 1 + 2 + 3 + 4 + 5
+ 6 + 7 + 8 + 9 + 10
で挙動が違うのは、慣れないと混乱する人もいるでしょう。
Re: (スコア:0)
RubyでもJavaScriptでも改行の次の行を見ないと分かれるのかわからないのは同じだし、逆に言えば次の行を見れば分かる。
Re: (スコア:0)
Rubyで次の行を見ないといけないのはどんな時ですか?
Re: (スコア:0)
たしかRuby 1.9くらいからこういう風に改行を入れられるようになりました。これで、obj.hoge.piyo.foo.barと同じように動きます。
この例のように、メソッドチェーンが長く連なると改行を入れたくなることがあります。
Re: (スコア:0)
>Cの配列インデックスがポインターの算術演算のような動作をすること
他にどうやって配列の中身を表せと。
1[a]と書けるとかの話をしている?
Cの配列インデックスってsyntax sugarと思っていなくて、本当に配列というものが存在しているかのように誤解しているんじゃなかろうか。関数の仮引数を配列形の書き方をしている人をみるとそういう気がする。
Re: (スコア:0)
逆に、ポインタと配列が同じなんて誰が言ったんだ、
と憤慨している文章を見たことがあります。
メモリの確保の仕方が全然違うだろうと。
確かにその辺は全然違いますね。
プログラミング言語なんてものは概念の世界のものなのだから、
どれが本当に存在しているかなんて議論は、
そもそも不毛なのかもしれませんね。
Re: (スコア:0)
void foo(char *a){
char b[3];
}
の、bは「本当に存在する配列」と違いますか?
スタックに積まれる物は、aは、「何かのアドレス」が1個だけ。bは、「b[0]」、「b[1]」、「b[2]」に相当する3つのcharになりますよ。
翻訳後の機械語の動作としても、別物になり、
x = *a; // 「スタックポインタ+コンパイル時に決まるaのオフセット(定数)」を計算→その番地の値を読み込む→その番地の値を読み込んで、xに代入
x = *b; // 「スタックポインタ+コンパイル時に決まるbのオフセット(定数)」を計算→その番地の値を読み込んで、xに代入
// a[0]、b[0]と書いても同様
Re: (スコア:0)
そんなことをいったら、a だってインライン展開の具合次第でなくなることはあるでしょう。
あんまり本質的な議論だとは思えません。
まさに、C Languageが「未定義」という必殺技を繰り出す最大の理由でしょう。
C99とかではかなり論調が変わってきたのも事実ですが・・・。
Re: (スコア:0)
いえ、aは、a++できますが、bは、b++できません。配列とポインタの本質的な違いです。
char *a = "abc";
char b[]="abc";
も本質的に違い、どちらにも異なる利点・欠点があります。
未定義動作と話が繋がるのかは想像できませんでしたので説明いただけると助かります。
Re: (スコア:0)
私が、言ったのは、
> bがスタック上のどこにあるのかをコンパイラは把握出来るので、出力する機械語にその値を直接埋め込んでしまえますから、
> 実行時に、「変数b」に該当するような値を覚えておく必要、メモリは不要になります。
という部分に対して、bが変数として保存される必要がないという部分に対してです。
話が分かりにくくて済みません。
一方で、
> いえ、aは、a++できますが、bは、b++できません。配列とポインタの本質的な違いです。
と言われると、C++プログラマとしては、
char const * const a = "abc";
なんていうヒネクレタ事も言いたくなる部分ではあります。
個人的には、sizeofの挙動以外、大した差ではないと思っていますが。
Re: (スコア:0)
char *p, a[1];
a[0] = 0; /* OK */
p[0] = 0; /* NG */
これで大した差がないと?
Re: (スコア:0)
char const * const a = "abc";
なんていうヒネクレタ事も言いたくなる部分ではあります。
いや、まじめに「配列とポインタには本質的な違いがある」という人に、このaはポインタなのか配列なのかを伺いたい。
形式的にはポインタだしsizeof(a)もポインタのサイズを返すが、性質としては配列というわけでしょう?
Re: (スコア:0)
大した差ではないな。
ケアレスミスを起こすかどうかって本質的な問題じゃないでしょ。
Re: (スコア:0)
え、まさか配列とポインタの違いも分からないの?
Re: (スコア:0)
それが大した差でないというなら、
sizeofの挙動の違い(に起因するミス)だってケアレスミスであり本質的な問題じゃないです。
Re: (スコア:0)
どうして混乱できるのでしょうか。
Re: (スコア:0)
void foo(char *a){
char b[3];
}
の、bは「本当に存在する配列」と違いますか?
スタックに積まれる物は、aは、「何かのアドレス」が1個だけ。bは、「b[0]」、「b[1]」、「b[2]」に相当する3つのcharになりますよ。
"配列"といった場合、そのデータの塊を1つとして扱いたいという意味もあります。
ここで sub_func(a), sub_func(b)とした場合、sub_func側で受けとるのは「何かのアドレス」aか,b[0]のアドレスかの違いでしかなく、配列の大きさの情報も,どういった領域のメモリかも受け渡しされません。
"b"という識別子だけで、b[0],b[1],b[2]に相当する3つの
Re: (スコア:0)
JavaScriptのArrayはただのオブジェクト、連想配列と言ったところで仕方ないもんな。
Re: (スコア:0)
>Cの配列インデックスがポインターの算術演算のような動作をすること
a[1]を*(a + 1)の糖衣構文と説明せず、配列同じですよと説明している本が多いから混乱する
Re: (スコア:0)
配列でも*(a + 1)の糖衣構文なことは同じなので、
配列と同じなのは確かではなかろうか?
Re: (スコア:0)
> Python全否定されているんだが。CoffeeScriptはいいのか?
そもそもCoffeeScriptとか知らない
Re: (スコア:0)
pythonからインデント取ったらなにものこらないし、何じゃこりゃとしか。
PHPのケースセンシティブも少なくともその機能が作られたとき必要なもので、まだi18nの概念が一般化する前とか考えたらそんなもんだし。
javaやjavascriptも実装依存に近い性格の癖だったり、その他も一緒かと。