tags:

views:

202

answers:

2

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;
}
+1  A: 

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;
}
Samir Talwar
Can someone now port this to Assembler?
webbiedave
Lua please.Also, I believe that C provides >>=, |=, etc operators.
DeadMG
just compiled it. You're right. Rolling back
Carson Myers
LISP, please. I need to test this in XEmacs.
Thomas Matthews
I am not a C guru but I wonder why this was downvoted?
Felix Kling
@Felix: Probably because it's just giving the exact answer to the OP instead of helping him figure out the actual problems he had?
jamessan
Tex, please. Not LaTex...
Paul Nathan
Thanks Samir Talwar. It works perfectly. DeadMG, >>= does not return the same results.
Tech163
@jamessan: Ok I can understand that. But at least I would expect a comment...
Felix Kling
@jamessan: That's fair enough. I figured seeing a working code sample would be beneficial too. Perhaps seeing the similarities between PHP and C in this case will help the OP. Perhaps it won't. Can't be sure until we try.
Samir Talwar
@jamessan, before I had http://pastebin.com/tmt2mAJ3, which always returned 0.
Tech163
Definitely gonna need this in INTERCAL next.
Tyler McHenry
Watch for the signed/unsigned difference. The 4th line, specifically, will be sensitive to that.
Seva Alekseyev
+4  A: 

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 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2^E2. If E1 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.

RBerteig
Although this works with all numbers, this doesn't work with all numbers. I've tried a similar method in PHP before, and it didn't work well. Thanks for your response though.
Tech163
This answer is right. It's not *possible* to "try a similar method in PHP", since PHP doesn't have an `unsigned int` type.
caf
Not knowing PHP I wasn't willing to make the bald assertion, but none of the fuss would be required if PHP did have an `unsigned` integer type and logical shift right.
RBerteig