Tech163
Tech163

Reputation: 44

Can someone port this to C?

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

Answers (2)

RBerteig
RBerteig

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 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.

Upvotes: 4

Samir Talwar
Samir Talwar

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

Related Questions