« 『博多ラーメンよかろうもん』で飲む♪ | トップページ | 三鷹夏祭り2009 »

2009年7月25日 (土)

負の数の表現…『0x80000000』は、駄目?

負の数を16進数とかで表現したい場合がある。
平たく言えば十進数に直すのが面倒なのだ…。

例えば16ビットサウンドでのボリュームの変更処理。
オーバーフロー対策で32ビットの『int/long』で処理するのが普通だと思う。
このオーバーフローをチェックするとこんな感じになるかと思う。

short    *WaveData;
double    Volume;
int    Wave    = *WaveData;
    Wave = ( int )( Wave * Volume );
    if( Wave < -32768 )
        Wave    = -32768;
    if( Wave > 32767 )
        Wave    = 32767;

でも『-32768 / 32767』なんて覚えないので…

    if( Wave < 0xFFFF8000 )
        Wave    = 0xFFFF8000;
    if( Wave > 0x00007FFF )
        Wave    = 0x00007FFF;

なんて書いてしまうと上手く動かない…。
そこで…

    if( Wave < ( int )0xFFFF8000 )
        Wave    = 0xFFFF8000;
    if( Wave > ( int )0x00007FFF )
        Wave    = 0x00007FFF;

と書くと上手く動く…。

謎だ…。(汗)

なので調べてみた…。

#include<stdio.h>
void main( void )
{
    __int64            i;
    int                j;
    short            k;
    for( i = j = k= 0 ; i < 0x100000000 ; i += 0x4000, k += 0x2000 )
    {
        j    = k;
        if( j < 0xFFFF8000 )
            printf( "8000:%08X\n", j );
        if( j > 0x00007FFF )
            printf( "7FFF:%08X\n", j );
    }
}

結果は、以下の値をループする。
8000:00000000
8000:00002000
8000:00004000
8000:00006000
...

マシン語で見てみると…。
51:           if( j < 0xFFFF8000 )
00401077   cmp         dword ptr [ebp-0Ch],0FFFF8000h
0040107E   jae         main+81h (00401091)

符号無しで比較している!(汗)
右側優先?それとも符号無し優先?

で『if( j < 0xFFFF8000 )』を『if( j < ( int )0xFFFF8000 )』にすると…

51:           if( j < ( int )0xFFFF8000 )
00401077   cmp         dword ptr [ebp-0Ch],0FFFF8000h
0040107E   jge         main+81h (00401091)

符号有りで比較している!

試しに『if( 0xFFFF8000 > j )』とかにしてやってみる…
が、結果変わらず…。

なので符号有りと符号無しの比較では、符号無しで判定されるようだ…。

確認の為に『unsigned int』でも確認してみる。

unsigned int l = 0xFFFF8000;
    ...
    if( j < l )
    ...

この場合…
『warning C4018: '<' : signed と unsigned の数値を比較しようとしました。』と
きっちり警告がでる!
構わず実行してマシン語を確認すると符号無しで比較していた。

ちなみにこうするとちゃんと符号付きで処理される。

int l = 0xFFFF8000;
    ...
    if( j < l )
    ...

多分、符号無し優先で判定するのは、仕様なのだろう。
でも、リテラル値が符号無しなら警告を出しても良いんじゃない?

こんな使い方をする奴なんかきっと想定外だったのかもしれない…。

結論!

負の数の表現…『0x80000000』は、駄目?

は、駄目!だった…。

2009年7月25日追記----------------

ちなみに『Microsoft Visual Studio 6.0』での事だ。
でも他でも起こるんだろうな…。

|

« 『博多ラーメンよかろうもん』で飲む♪ | トップページ | 三鷹夏祭り2009 »

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック


この記事へのトラックバック一覧です: 負の数の表現…『0x80000000』は、駄目?:

« 『博多ラーメンよかろうもん』で飲む♪ | トップページ | 三鷹夏祭り2009 »