I wanted a fast count of the number of set (clear) bits in a string.
I'm getting rather strange results, and I haven't found a clue in
the docs or archives. Here's the code:

use Inline C => q{
    char b_set[256];
    char b_clear[256];
    void bc_init() {
        int i, j = 1;
        b_set[0] = 0;
        while (j < 256) {
            for (i = 0; i < j; ++i) {
                b_set[i + j] = 1 + b_set[i];
            }
            j <<= 1;
        }
        for (i = 0; i < 256; ++i) {
            b_clear[i] = b_set[255 - i];
        }
    }
    UV cset(char* pv, UV len) {
        UV s = 0;
        UV i = len >> 3;   # len gives string length in bits
        while (i--) { 
            s += (UV)b_set[*pv++];
        }
        return s;
    }
    UV cclear(char* pv, UV len) {
        UV s = 0;
        UV i = len >> 3;   # len gives string length in bits
        while (i--) { 
            s += (UV)b_clear[*pv++];
        }
        return s;
    }
};  

I've had various permutations of this, and mostly the results seem
pretty random, then occasionally a particular permutation will give
the right results for one of the cset() or cclear() functions, or
will give the results expected for the other function:

warn sprintf "size: %s, set/clear: %08x/%08x (%s)\n",
  $size,
  scalar cset($s, $size),
  scalar cclear($s, $size),
  join '', map sprintf("%02x", ord($_)), split //, $s;

size: 64, set/clear: 00000001/00000000 (fffffffffffffffb)
size: 64, set/clear: 00000004/00000000 (ffffffffffff9eef)
size: 64, set/clear: 0000000a/00000001 (ffffffffffff977f)
size: 64, set/clear: 00000003/00000040 (ffffffffffdfd7ff)
size: 64, set/clear: 00000001/00000040 (fffffffffffff7ff)

(The permutations are minor variations to the functions, not
attempts to declare stuff differently.)

Do I need to do something special to declare static variables?
Or is this perhaps something you can't do at all? (None of the
examples in C-Cookbook, by the way, use a static variable.)

Hugo

Reply via email to