CとC++の型パンニング、ポインタキャストは-O2で静かに壊れる
Type Punning in C and C++
CとC++でメモリを別の型として解釈する型パンニング。安全なのはunionとmemcpyで、ポインタキャストは厳密な別名規則により未定義動作だ。C++ではコンパイラが異なる型は別名にならないと仮定でき、-O2でコードが黙って最適化される。著者はfloat*からuint32_t*へのキャストで実際に踏んだバグを例に、その危険性を解説する。
ポインタキャストは「動く」が、動かなくなるときが来る。そして「動かない」とは、コンパイラが実行されていると思っていたコードを黙って最適化で消してしまうことを意味する。
HNでの議論
23- eqvinox
「Why C and C++ Differ」の下に載っている例は、CでもC++でもUBだ(しかもCとC++が「なぜ」違うのかについては何も言っていない)。記事全体が間違っているわけではないが、その部分はただ……
(LLMのジャンクっぽくも感じるが、正直よくわからない。)
- scoopr
ちょうど今見た動画[0]で、constevalできるならUBがないはずだという主張をしていて、少なくともこうした低レベルのヘルパーに関しては説得力があるように思えた。
残念ながらmemcpyはconstexprではないのでこのようには使えないが、std::bit_castは実際にconstexprとして動作する[1]ので、C++では今やこれが最も好ましい使い方だと思う。unionも許さないだろう。
- antiloper
> ここでのC対C++の区別は本当に危険だ
この「本当に」って何がそんなに本当なんだ?