int pcount_r (unsigned x) {
if(x==0)
return 0;
else
return ((x & 1) + pcount_r(x >> 1));
}
なぜ入力引数が符号なしなのか疑問に思っています。
よろしくお願いします!
int pcount_r (unsigned x) {
if(x==0)
return 0;
else
return ((x & 1) + pcount_r(x >> 1));
}
なぜ入力引数が符号なしなのか疑問に思っています。
よろしくお願いします!
E1 >> E2
これは、E1が符号付きタイプで負の値(C99 6.5.7:5)の場合に生成される実装定義です。一方、E1 >> E2
規格では明確に定義されています。符号なし整数を受け入れて操作することは、関数を最も移植性の高いものにする方法です。
ちなみに、ビットをいじるには符号なしの型を使うのが普通です。
数値が符号付きの場合、右シフトによって符号ビット (最後のビット) がコピーされ、事実上、負の数に無限のビット数が与えられます。
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);
}
問題は、C (Java とは異なり) が符号付き (算術) シフトをサポートしていないことです。CPU には、符号付きと符号なしの 2 種類のシフト演算子があります。たとえば、x86 では、SAR 命令は算術右シフトを実行し、SHR 命令は符号なし右シフトを実行します。C には右シフト演算子 (>>) が 1 つしかないため、両方をサポートすることはできません。コンパイラが符号なしシフト (SHR) を使用して上記のコードを実装し、そのプロシージャに負の数を指定すると、間違った答えが得られます。