Reputation: 44
I've spent the last few hours trying to port this to C, with no success. Can someone please help?
function zerofill($a, $b) {
$z = hexdec(80000000);
if ($z & $a) {
$a = ($a>>1);
$a &= (~$z);
$a |= 0x40000000;
$a = ($a>>($b-1));
} else {
$a = ($a>>$b);
}
return $a;
}
Upvotes: 0
Views: 267
Reputation: 43366
How about
unsigned int zerofill(unsigned int a, int b) {
return a >> b;
}
Or,
int zerofill(int a, int b) {
return ((unsigned int)a) >> b;
}
In C, the right shift operator acts as an arithmetic shift if its left operand is signed, or a logical shift if unsigned. It appears that the original PHP code is going to some lengths to get an unsigned shift using only a signed shift.
The C99 standard at section 6.5.7 says:
The result of
E1 >> E2
isE1
right-shiftedE2
bit positions. IfE1
has an unsigned type or ifE1
has a signed type and a nonnegative value, the value of the result is the integral part of the quotient ofE1 / 2^E2
. IfE1
has a signed type and a negative value, the resulting value is implementation-defined.
This says clearly that to get zero bits shifted in, the operand must be either unsigned, or signed and positive. The only question is the behavior when the operand is signed and negative where the result is implementation defined. In practice, every implementation I've encountered has treated that case by sign extension so that the result still makes sense as a division by a power of two when integer values are stored as two's complement.
I don't have the reference at hand, but C89 said effectively the same thing, and established practice before the C standard was also consistent with this interpretation.
Upvotes: 4
Reputation: 14330
Untested, but then, most of the code is the same.
int zerofill(int a, int b) {
int z = 0x80000000;
if (z & a) {
a = a >> 1;
a &= ~z;
a |= 0x40000000;
a = a >> (b - 1);
} else {
a = a >> b;
}
return a;
}
Upvotes: 1