0

以下のコードは、いくつかの10進数を出力しているときに、一見無限のループになってしまいます。

int main(){
    show(0xBADECAFU);
}

void show(unsigned a){
    unsigned pos=0;
    for(; pos<UINT_MAX; pos++)
        printf("%u", (1U<<pos) & a);
}

以下のコードは、実際には16進数のビットを示しています。最初のプログラムが正しく実行されないのに、2番目のプログラムが正しく実行されないのはなぜですか?

int main(){
     show(0xBADECAFU);
}

void show(unsigned n){
    unsigned pos=31, count=1;
    for(; pos!=UINT_MAX; pos--, count++){
        printf("%u", n>>pos & 1U);
}
4

3 に答える 3

4

UINT_MAXにビットはありませんunsigned int。ただし、CHAR_BIT * sizeof(unsigned int)ビットがあります。

/* nb: this prints bits LSB first */
void show(unsigned a){
    unsigned pos=0;
    for(; pos < CHAR_BIT*sizeof(unsigned); pos++)
        printf("%u", (1U<<pos) & a ? 1 : 0);
}

posに等しくなるまでループする2番目のケースを考えてみましょうUINT_MAX。これにより、アンダーフローが少なくとも4になり、少なくとも4であると仮定して、32ビットが適切に出力されます。unsigned~0sizeof(unsigned)

2番目の例は、わずかに改善される可能性があります。

void show(unsigned n){
    int pos = (CHAR_BIT * sizeof(unsigned)) - 1;
    for(; pos >= 0; pos--) {
        printf("%u", (n>>pos) & 1U);
    }
}

*ビットを「印刷」するコードは奇妙で、私の例では修正しました。

于 2012-04-27T01:48:41.313 に答える
2

UINT_MAXは、unsignedint変数に格納できる最大値です。ビット数とは直接関係ありません。

最初のループは、膨大な数のintを超えて増分しています。

2番目のループは31から???に減少しています。(署名されていないので、0をデクリメントするとどうなりますか?-ラッキーで0-1 = UINT_MAXのように見えます)

于 2012-04-27T01:53:29.153 に答える
0

これは単なる推測です。

(1U<<pos)最初のものの問題は、の場合に未定義の動作を呼び出すことだと思いますpos >= (sizeof(unsigned int) * CHAR_BIT)。このような場合、コンパイラーは自由にやりたいことができます。このような状況は決して発生しないと想定される場合があります。したがって、常にそうであるpos必要があります。したがって、ループ条件を最適化することができます。残念ながら、この「最適化」により、無限ループが発生します。< (sizeof(unsigned int) * CHAR_BIT) < UINT_MAX

于 2012-04-27T04:24:38.967 に答える