1
uint64_t bitsToInt64(char *bs) {
    uint64_t r, i;
    r = 0;
    for(i = 0; i < 64; i++)
        if(bs[i] == 1) 
            r |= 1LL << i;          
    return r;
}

int countBits64(uint64_t i) {
    uint64_t x, t;
    t = 0LL;
    for(x = 0LL; x < 64LL; x++) {
        if(i & (1LL << x))
            t += 1;
    }
    return t;
}

char bits [] = { 
    0, 0, 0, 0, 1, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    1, 1, 1, 1, 1, 1, 1, 1,};

uint64_t mask = bitsToInt64(bits);
int nbits = countBits64(mask);
printf("%d", nbits);

上記は「1」を印刷しています。私は何を間違っていますか?

4

2 に答える 2

2

1LL署名されている をシフトすると、未定義の動作が発生します。したがって、64 ビットの符号付き整数を 63 ビットシフトすると、コンパイラに面白いことをさせることができます (たとえば、鼻からデーモンを飛ばすなど)。

1ULL << xこの場合の解決策は、代わりに使用することです。

LLVM の Chris Lattner によるこの優れた記事も参照してください。この記事では、このようなことが奇妙な動作につながる理由を説明しています。

于 2011-06-30T19:48:03.297 に答える
1

以下のコードで、私は次の出力を得ることができました

(0xFF00000000000010)9

正しいサイズ値を使用していることを確認してください。リテラル定数はULL、uint64_tと一致する必要があり、forループ変数はintと、の戻り値のみである必要がありますcountBits64

uint64_t bitsToInt64(char *bs) {
    uint64_t r;
    int i;
    r = 0;
    for(i = 0; i < 64; i++)
        if(bs[i] == 1) 
            r |= 1ULL << i;          
    return r;
}

int countBits64(uint64_t i) {
    int x, t = 0;
    for(x = 0; x < 64; x++) {
        if(i & (1ULL << x))
            t += 1;
    }
    return t;
}

char bits [] = { 
    0, 0, 0, 0, 1, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    1, 1, 1, 1, 1, 1, 1, 1,};

uint64_t mask = bitsToInt64(bits);
int nbits = countBits64(mask);
printf("(0x%016llX) %d",mask, nbits);
于 2011-06-30T19:45:49.923 に答える