質問: x64のWindows上でCプログラミングをしている途中に、`malloc`で確保して`unsigned long`(Windowsでは32ビット)の配列として値を詰め込んだ領域を、`unsigned long long`の配列として読み替えたくなる場面が出てきました。そこからいろいろ気になっての質問なのですが、 質問1:strict aliasing ruleについて調べてみたところ、互換性のない型で「書き込んだ」場合に未定義な動作となるというように読めるのですが、`unsigned long`で書き込んだものを`unsigned long long`として読み取るだけでは未定義の動作とはならない、という解釈で間違いはないでしょうか(もちろん、最後に出る端数については`unsigned long long`アクセスしない前提です)。 質問2:質問1とは逆に、`unsigned long long`の配列として書き込んだ値を`unsigned long`の配列として読み書きしたいとします(もちろん、この2つのサイズが違う環境での話です)。スカラー値であれば、共用体を介してアクセスすることでstrict aliasing ruleをクリアできます。ただ、共用体の配列としてアクセスするのはどうにも不便となってしまいます。このような場合に、「コンパイラ独自の記法によってstrict aliasing ruleを使った最適化を抑える」という手段以外に、未定義の動作を避けつつ正しく行うには、「配列丸ごとコピーする」以外の手段はないものでしょうか。 --- (注:むろん、このような操作が「処理系定義」となるのは承知ですが、今回はそれについては考えなくて大丈夫です。また、符号なし整数について詰め物ビットはなく、よってトラップ表現が発生する可能性もないものとします)
回答: メモリ領域に対する操作なら**実用上は**問題ないように思います。というか、同じようなことは私もこれまで何度となくやっていたような気が......。 `unsigned long`のポインタも`unsigned long long`のポインタも、同じアドレスを指している限り、同じアドレスへの操作となるはずです。最適化において「ある変数が別のポインタ変数によって書き換えられる可能性を考慮するかどうか」が問題となるのであって、ご質問のように両方ともポインタによる間接アクセスでは該当しないような気がします。そのような手法はテクニックとしてはごく一般的ですし。 と、書いてみたものの、命令スケジューリングで前後して意図した通りにならない可能性は否定できないですね。コンパイラーがどこまで頑張るか(空気読むか)にもよるでしょうけど。 `union`を使うのが無難でしょうか。