1

ビットマスキングや型キャストが期待どおりに機能しない状況があります。私は、いくつかの部分が 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
4

2 に答える 2

2

これが私のgcc(4.6.2)が生成するものですmask(最適化あり。最適化なし、その周りに毛羽立ちがあります):

.LFB0:
    .cfi_startproc
    movl    4(%esp), %eax
    andw    $511, %ax
    ret
    .cfi_endproc

したがって、実際には下位 16 ビットのみを変更し、上位 16 ビットを実際に 0 にするのは呼び出し元の責任です。

movzwl  %ax, %eax

これは、呼び出しサイトで正しいプロトタイプがわかっている場合に行われます。私はそれを非常に強く疑っています

マスク関数のプロトタイプがきちんと含まれています。

は実際には正しくありません。確認して再確認してください。それが本当なら、重大なバグを発見したことになります (非常に重大なため、おそらく聞いたことがあるでしょう)。

uint16_tuint32_tlinux/types.h をインクルードすることで提供されます。

うーん、ここではありません。によって提供されstdint.hます。#include <stdint.h>システムで提供されている場合でもlinux/types.h、移植可能なソリューションであるため、とにかく入手する必要があります。

于 2013-03-19T16:06:39.067 に答える
0

ここで見られる唯一の説明は、期待されるマスク関数が呼び出されていないということです。サンプル コードを 1 つのファイルでのみ試すか、マスク関数の名前を変更してください。値 (0x10000) のビットと (nr & 0x1ff) は常にゼロになるはずです。

于 2013-03-19T15:44:21.800 に答える