3
int pcount_r (unsigned x) {
    if(x==0)
        return 0;
    else
        return ((x & 1) + pcount_r(x >> 1));
}

just wondering why the input argument is unsigned.

best regards!

3 Answers3

3

It is implementation-defined what E1 >> E2 produces when E1 has a signed type and negative value (C99 6.5.7:5). On the other-hand, E1 >> E2 is unambiguously defined by the standard. Accepting and operating on an unsigned integer is a way to make the function most portable.

Incidentally, it is usual to use unsigned types for bit-twiddling.

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
2

If the number is signed, then right-shifting will copy the sign-bit (the last bit), effectively giving negative numbers an infinite number of bits.

int pcount_r(int x) {
    if (x == 0)
        return 0;
    else if (x < 0)
        return sizeof(int)*8 - pcount_r(~x);
    else
        return (x & 1) + pcount_r(x >> 1);
}
Markus Jarderot
  • 86,735
  • 21
  • 136
  • 138
-2

The problem is that C (unlike Java) does not support signed (arithmetic) shifts. CPUs have two different types of shift operators, signed and unsigned. For example, on an x86, the SAR instruction does an arithmetic shift right, and SHR does an unsigned shift right. Since, C only has one shift right operator (>>), it cannot support both of them. If the compiler implements the code above using an unsigned shift (SHR) and you supply a negative number to that procedure you will get a wrong answer.

Tyler Durden
  • 11,156
  • 9
  • 64
  • 126
  • On the contrary - if it used `shr` it would *always* be correct. The problem arises when `sar` is used and the input has the signbit set, the algorithm would never terminate. – harold Oct 25 '12 at 19:44
  • “C only has one shift right operator (>>), it cannot support both of them” I do not understand how this is different from saying “C has only one addition (+), so it cannot support both of integer and floating-point”. And indeed, the choice to compile `>>` into SAR or SHR is made by the compiler by applying exactly the same rules that allow it to determine whether integer or floating-point computations are intended. C99 6.3.1.8: “Many operators that expect operands of arithmetic type cause conversions and yield result types in a similar way. The purpose is to determine a common real type…” – Pascal Cuoq Oct 25 '12 at 19:51
  • @harold if SAR is used then the program will terminate correctly because 1/2 = 0 with SAR. If SHL is used then the program will also terminate but will give a wrong answer because the sign bit will add one to the count. – Tyler Durden Oct 25 '12 at 20:03
  • @TylerDurden 1 >> 1 = 0, but -1 >> 1 = -1 (with `sar`). As for the signbit adding one, well, it is on, so you have to count it, right? – harold Oct 25 '12 at 20:08
  • @Pascal Cuoq The C standard does not define how to interpret ">>". The reason for this is that in the old days ">>" was mapped directly to SHR on the CPU and on some CPUs it was an arithmetic shift, and others it was unsigned, so there was no way to predict what the result would be. – Tyler Durden Oct 25 '12 at 20:11