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

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

余談だけど、整数値の2変数を入れ替える(swapする)テクニックとして xor演算による a^=b^=a^=b; というのを見かけたりするけど、これも同じ理由で未定義。やっちゃいけない。( a^=b; b^=a; a^=b; と式を分けるなら問題ない )

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

で、話を戻して x=x++; の未定義だとついつい「xの値はおかしくなるかも知れないけどそれだけの話じゃ…?」と思いたくなるのがありがちだとは思う。でもプログラム全体が無保証になる。( もちろん x だけの話で済むような結果になるかもしれない )

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

なぜかと言うと単純な話で、「xだけの話で済ませる」のだと「それ以外に問題が出ないように『保証』する」必要があるから。「保証外」って言ってるのに、その範囲を限定すること自体がまあ不自然だよね、と。

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

これ納得いかない人、わざわざ封印を破ってパソコンとかスマホの開けてはいけない蓋なんかを開けて「ちょっと蓋を開けただけなのに動かなくなった。どういうことだ。保証外? 何とかしろ!」とか言い出す人なんじゃないかな。

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

ということで、これが「未定義」の話。で、「難しい」とか「色々覚えなきゃ」とか言い出す人もいるんだけど、単純に「ルール守れ」なだけなので、難しいはずがないんだよね。 ※注意すればルールを守るのなんて簡単なはずだ、とかそういう意味じゃないからね。念のため

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

「色々ある」って言っても、そりゃルールくらい色々あるだろうって話だし、実際問題として「初期化してない変数使わないでね」とか「配列外参照だめよ」とか「無効なポインタ経由で間接参照しないでね」とか。1つ1つは常識的なルールでしかないし。

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

で、この話実は「〇〇するとどうなるか試してみました!」「取り敢えず書いて動かしてみよう!」ってのがマズいよね、という話にもつながってる。

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

なんでマズいのか、理由は簡単で「ルールに照らし合わせて判断する」っていう姿勢が皆無だから。( もちろんルールに則った上で色々試すのであればなんら問題ない )

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

「未定義は無保証」って話をしてきたわけだけど、これはつまり「うまく動いているように見えても実はコード自体は未定義を含んでいる」って可能性があるわけで。だから「まずはルールどうなってるんだ」を意識できないとマズいよ、と。

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

現実でも例えば「この前赤信号で道渡ったけど大丈夫だった。だから赤信号って大丈夫」とか言ったら「頭大丈夫か」って扱いになるでしょ。「その時は大丈夫だったのか知れんけど次どうなるか分からんし、何よりルール違反だろ」と。それと同じこと。

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

「プログラムは書いた通りに動く」って言葉あるけど、これもあんまり良くはないよね。「思った通りに動かない」って話だから文脈が違うんだろうけど「書いたらなんらか決まった動作になる」と曲解する人が出るから。

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

それでなんか「(規格で)未定義であっても(各処理系では)なんらか定義されるはず」とか嘘言い出す人もたまにいる。当然間違いで「書いた通りに動く」ってのはあくまで「ルールを守って書いていれば」の話。とにかくルールの存在を意識しようね、という話でした。

2023-12-21 20:59:36