ビットマスキングや型キャストが期待どおりに機能しない状況があります。私は、いくつかの部分が i C で書かれている、圧倒的に大きな分散システムで作業しています。
私を混乱させる数行のコードは次のとおりです。
uint16_t
mask(uint32_t nr)
{
return (uint16_t)(nr & 0x1ff);
}
...
int nr = 65536;
int index;
index = mask(nr);
...
この場合、マスクの戻り値は 65536 であり、期待どおりの 0 ではありません。この例には一貫性のない型変換がいくつかありますが、結果がどのように間違っているのか理解できません。基本的に、32 ビット整数の下位 9 ビットをマスクして、結果を 16 ビット整数に変換しています。私の最善の推測では、最初の 16 ビットを変更するコンパイラの最適化がいくつかありますが、16 ビットのみを返したいため、上位 16 ビットについては何もしません。この場合の「インデックス」は 32 ビット整数であるため、ビットマスクで変更されていない「nr」の 17 番目のビットも含まれます。したがって、17 番目のビットは 1 に設定され、インデックスに 65536 が割り当てられます。 .
この動作の説明を持っている人はいますか?
編集:いくつかの重要なパラメータを忘れました。マスク関数のプロトタイプがきちんと含まれています。このシステムは、gcc 4.3.2 を使用する Linux x86 用に構築されています。
Edit2: アセンブリ コード:
0805b640 <mask>:
805b640: 55 push %ebp
805b641: 89 e5 mov %esp,%ebp
805b643: 83 ec 18 sub $0x18,%esp
805b646: 65 a1 14 00 00 00 mov %gs:0x14,%eax
805b64c: 89 45 fc mov %eax,0xfffffffc(%ebp)
805b64f: 31 c0 xor %eax,%eax
805b651: 8b 45 08 mov 0x8(%ebp),%eax
805b654: 66 25 ff 01 and $0x1ff,%ax
805b658: 8b 55 fc mov 0xfffffffc(%ebp),%edx
805b65b: 65 33 15 14 00 00 00 xor %gs:0x14,%edx
805b662: 75 02 jne 805b666 <maks+0x26>
805b664: c9 leave
805b665: c3 ret
805b666: e8 a5 ac 04 00 call 80a6310 <__stack_chk_fail_local>
805b66b: 90 nop
805b66c: 8d 74 26 00 lea 0x0(%esi),%esi