C言語の未定義動作についておさらい

ものすごく基本なのにあんまり理解されてないものに、C言語の未定義(な動作)ってのもあるよね、ということでおさらいしてみたもの
9
angel (as ㌵㌤の猫) @angel_p_57

ちょっと前に「未定義(な動作)」のこと ( 基本的にC言語前提ね ) をちょっと話題にしたことがあったけど。 こういうの見てるとやっぱりちょっとマズいよなあ、と思える。 ※別にこの人が特別ということではなく、認識がマズい人が多すぎる twitter.com/rsk0315_h4x/st…

2023-12-21 20:42:30
えびちゃん🍑🍝🦃 @rsk0315_h4x

未定義動作、あくまで動作が未定義なだけで、「未定義動作のコードを書いてはいけません」と言われると、「それは押しつけじゃない?」という気分になる(未定義動作を書いた方がいい場面というのはないとも思いつつ)

2023-12-19 21:34:35
angel (as ㌵㌤の猫) @angel_p_57

別に詳しく知ってる必要はなくて「よく分からんけどやっちゃダメなんだよね」くらいでも全然構わないんだけど。なんか変に齧った人がズレたこと言い出すんだよね。

2023-12-21 20:42:58
angel (as ㌵㌤の猫) @angel_p_57

これについては、既に30年近くも前からFAQに挙げられてる話で。( というか基本中の基本過ぎて、簡単にでもいいから把握してないとヤバい ) 「未定義のコードは間違い」「未定義のコードは絶対に書くべきではありません」もう、これに尽きるのよ。 st.rim.or.jp/~phinloda/cqa/…

2023-12-21 20:43:16
angel (as ㌵㌤の猫) @angel_p_57

あ、まあ、趣味でプログラム書いてて自分のPCでしか動かさない、それでマズいことがあっても気にしない、結果が他へ影響することはない、そういう場面で「それでも自分は未定義のあるコードを書きたい」というのまでは止めない。

2023-12-21 20:43:43
angel (as ㌵㌤の猫) @angel_p_57

あと一部、特殊な場面だけど、コードゴルフなら ( ひょっとしたら競技プログラミングでも ) 許容はされる。あれは「用意されたシステム上で」「その時だけでも」動作規定を満たしたコードであれば拒否はされないものだから。

2023-12-21 20:43:59
angel (as ㌵㌤の猫) @angel_p_57

でも通常、プログラムを書くのはそういうのに当てはまらないからね。「未定義」と言ったら「ダメ」なのは当然、そうコーラを飲んだらゲップが出るっていうくらい当然の話ということになる。

2023-12-21 20:44:31
angel (as ㌵㌤の猫) @angel_p_57

それでも認識がマズい人が後を絶たないのは…。まあ、ロクな入門書や解説テキストが無い( 普及してない )からというのが一番だろうなとは思うんだけど、それ以外にも言葉の持つイメージだったり、「利用者向けの」説明の甘さがあったりするからなのかな。

2023-12-21 20:44:56
angel (as ㌵㌤の猫) @angel_p_57

さっきのFAQを代表として至る所探せば書いてある話なはずというのはあるにしても。 st.rim.or.jp/~phinloda/cqa/…

2023-12-21 20:45:14
angel (as ㌵㌤の猫) @angel_p_57

このFAQを始めとして、大体は「規格」の文面への忠実さを重視しているためか、ぱっと見分かり辛い面はあるかも知れない。規格って「言語環境 ( 要はコンパイラ等 )を作る人」向けに作られているから。

2023-12-21 20:47:59
angel (as ㌵㌤の猫) @angel_p_57

なので、利用者 ( 要はプログラマ ) 向けの言葉ではどうか、と。 で、私が説明するとしたら「未定義(な動作)」というのは「プログラム全体が無保証になるルール違反」だ、となる。

2023-12-21 20:48:23
angel (as ㌵㌤の猫) @angel_p_57

大事なのは2点。「ルール違反だから保証がなくなる」という話と、「その範囲が全体に及ぶ」ということ。特に「ルール違反」なんだから、「ダメ」なのは当然なんだ、ということになる。

2023-12-21 20:48:47
angel (as ㌵㌤の猫) @angel_p_57

なんか「ルール違反」という意識が抜けてる人が認識をこじらせているんじゃないかなと思う。で、こういうこと書いてると「お前の勝手な言い分じゃないのか」とか言いたがる人が出てきそうなものだけど。

2023-12-21 20:49:07
angel (as ㌵㌤の猫) @angel_p_57

でも、規格見るとちゃんと書いてある。「『…(し)なければならない』『…(し)てはならない』という要求をプログラムが守っていない場合」と。 ( これが全部じゃないけど ) つまり、明確にルール違反に関する話。

2023-12-21 20:49:31
angel (as ㌵㌤の猫) @angel_p_57

なので、利用者に対しては「ルールはちゃんと守ろうや」って話だし、環境を用意する人に対しては「ルール守ってなかったら保証しなくていいからね」ということになる。「未定義」という言葉尻だけ見て単に「決まっていない」って考えると多分相当認識にギャップが出る。

2023-12-21 20:50:02
angel (as ㌵㌤の猫) @angel_p_57

ちなみに「無保証」ってどういうこと? って言うと、割とそのままなんだけど「何が起こっても文句言えない」これが「鼻から悪魔」とか言われるものの正体。

2023-12-21 20:50:23
angel (as ㌵㌤の猫) @angel_p_57

で、「エラーとどう違うの?」と疑問に思う人もいるかも知れないけど、エラーは明確に「不具合が起こったことを知らせる/システムに反映する挙動」であって、「無保証」だとエラーになるかも知れないし、何事もなかったように見えるかもしれない。とにかくどうなるか分からない。

2023-12-21 20:50:51

これも言っておかないとマズそうな気がするので追加。
「何が起こるか分からない」は「『その挙動が再現性がある』かすら分からない」ということなので注意。
たまに「プログラムである以上なんらか動きは決まってる(はず)」とか言い出す人は、多分このことがすっぽり意識から抜けている。

angel (as ㌵㌤の猫) @angel_p_57

これを見ると「なんて無責任な! マズいことだと分かってるならシステム側で明確に対処しろ!」と思う人も出てきそうなんだけど。まあ確かに対処できるなら親切ではあるけどね。

2023-12-21 20:51:25
angel (as ㌵㌤の猫) @angel_p_57

でも、基本的にトラブルの種になるのは「文法的には合ってるけどルール違反」だとか「実際にプログラムを動かすとルール違反になる状況がある」とかそういうのなので。だから「エラー」じゃなくて「無保証」という扱いにせざるを得ない面がある。

2023-12-21 20:51:47
angel (as ㌵㌤の猫) @angel_p_57

現実で近い話だと、こういうのを想像してほしい。例えば「電子レンジに(身体を乾かすような目的等で)猫等のペットを入れるな」って言うのは、多分作り話が元だけど有名な話なんじゃないかと思う。

2023-12-21 20:52:14
angel (as ㌵㌤の猫) @angel_p_57

ここで「入れてはいけないんだったら影響を明らかにせよ」とか「マズいと分かってるならなぜセンサー等で対策しないのか」って言い出したら頭オカシイってなるだろう。「目的外の使用でどうなるか責任取れないからやるなっつってるんだよ!」と。

2023-12-21 20:52:40
angel (as ㌵㌤の猫) @angel_p_57

これと同じ話。「ペットを入れないでください。『保証外』です ( なにがあっても責任取れません )」これに相当するのが「〇〇しないでください。未定義(な動作)です」ということ。

2023-12-21 20:53:02
angel (as ㌵㌤の猫) @angel_p_57

一応補足すると、規格的には「何をしてもいい」なので、システムによっては「規格では『未定義』だけど、うちでは〇〇になるってことにするよ」と保証をつけることもありえる。ありえるんだけど…。規格で敢えて「無保証」って言ってるのをわざわざケアしないよね、大体の場合は。

2023-12-21 20:53:41
angel (as ㌵㌤の猫) @angel_p_57

もう一つ挙げた「(無保証となる)範囲がプログラム全体」これも「保証」という観点で考えれば、特に不思議でもなんでもないんだけど、一応説明しておく。

2023-12-21 20:54:01
angel (as ㌵㌤の猫) @angel_p_57

たまに取り上げられる形で例えば x=x++; みたいな式も未定義に該当する。何故かと言うと、同じ式の中で x の更新が2回(以上)発生しているから。形が似ていても y=x++; だったら該当しない。

2023-12-21 20:54:27