早速ですが、下記のような実装があった場合、代入された変数の値はどうなるでしょうか?
WORD wHoge = -1;
DWORD dwHoge = wHoge;
DWORD dwCastHoge = (DWORD)wHoge;
int nHoge = wHoge;
int nCastHoge = (int)wHoge;
結論から申し上げますと、これらの代入後の変数の「値は全て65535」となり、-1ではなくなり(=符号が無くなる状態)ます。
WORD型はunsigned short型ですので、同じく符号なしのunsigned int型のDWORD型に入れたら符号が無しの65535となるのは理解できます。
しかしながら、符号ありのint型にキャストをしても符号が無くなる…というのは腑に落ちない結果です。
【補足】
int型で-1の値は0xFFFFFFFFですが、00FFFFとなってしまい、65535となりました。
ちなみに、今回のケースで正しいキャストは何だったかというと、
WORD wHoge = -1;
int nHoge = (short)wHoge;
一旦2バイトで符号ありのShort型にキャストすることで-1(=0xFFFFFFFF)の値となります。
この時のコンパイル後のアセンブラを下記に比較してみます。
・int nHoge = (int)wHoge;
007DE049 movzx eax,word ptr [wHoge]
007DE04D mov dword ptr [dwHoge],eax
・int nHoge = (short)wHoge;
007DE065 movsx eax,word ptr [wHoge]
007DE069 mov dword ptr [dwShortCastHoge],eax
movzx:代入の余剰領域を0で埋める
movsx:代入の余剰領域を元の値が負ならFで、正なら0で埋める
こんな感じで小さな型を大きな型に入れるときに生成されるアセンブラのニーモニックが異なってきます。
- intキャストでダメだったのは、元の型がunsignedなのでmovzxが選択されたためです。
開発環境によってはうまく行くケースもあるかと思いますが、今回のようにNGとなるケースも実際にあります。
ですので、クロスコンパイル向けの実装では特に注意しなければいけません。
POINT型の座標値X,YをMAKEDWORDして後で分解した際に、符号が吹き飛んで変な動作をしていたというのが実際の状況だったのですが、大きな型への代入では符号の保持というのも気をつけて対処する必要があります。

