Why is this C arithmetic shift implementation not working?
<p>I'm trying to write a C function that will always find the arithmetic right shift of an unsigned integer argument, using bitwise operators. I managed to write a function that would always find the logical right shift of a signed integer using bitwise operators, but the same idea doesn't seem to be working for finding the arithmetic shift. </p>

<p>Here's my function right now:</p>

<pre><code>unsigned arith(unsigned x, int k) {
    unsigned x_arith = (int) x &gt;&gt; k;

    x_arith = x_arith | ((-1&lt;&lt;(sizeof(x_arith)*8)-k)) &amp; ~(-1&lt;&lt;(sizeof(x_arith)*8));
    return x_arith;
}
</code></pre>

<p>Explanation:</p>

<pre><code>(-1 &lt;&lt; (sizeof(x_arith)*8-k))
</code></pre>

<p>Create an all-1's binary then shift those ones so that the first 1 aligns with the leftmost 1 in <code>x_arth</code>.</p>

<pre><code>&amp; ~(-1 &lt;&lt; (sizeof(x_arith)*8))
</code></pre>

<p>Create an all-1's binary and shift it so the first one aligns after the leftmost bit in <code>x_arth</code>, then flip it, then keep only those bits in common with the binary above. </p>

<p>This whole process supposedly creates a mask that has 1's where <code>x_arith</code> needs to have ones. Finally, I <code>|</code> (or) the original <code>x_arith</code> with this mask to get the 1's that I need to make the shift arithmetic and return the result.</p>

<p>However, the result is still a logical shift. I tried changing many things in the above code and got really frustrated with the weird numbers I got. What am I doing wrong?</p>

<p>UPDATE:
The function posted above does actually find the arithmetic shift. The problem was that I was testing it with 4 and k=1, expecting the result to be 6, which turns out to be <em>not</em> how arithmetic shifting works. Here's a nicer-looking version of the function for future reference:</p>

<pre><code>unsigned arith_shift(unsigned x, int k) {

    unsigned x_arith = (int) x &gt;&gt; k;

    int bits = sizeof(int) * 8;

    unsigned mask = k? ((~0 &lt;&lt; (bits-k)) &amp; ~(~0 &lt;&lt; bits)): 0;

    return x_arith | mask;

}
</code></pre>

<p>Note that you can use both <code>-1</code> and <code>~0</code> for an all-1's binary number. However, this function <em>may</em> behave differently on different machines since the behavior of left-shifting <code>-1</code> is undefined (see e0k's answer).</p>