Search code examples
cbitstandardssignedrepresentation

Does c standard guarantee bit pattern interpretation for signed and unsigned?


Does the C standard state how bit representations should be interpreted? In other words do the following if conditions always evaluate to true? Assume sizeof (int) = 4 and CHAR_BIT = 8

unsigned u = 0xffffffff;
if (u == 4294967295) /* do something */

int i = 0xffffffff;
if (i == -1) /* do something */

unsigned u = (int)0xffffffff;
if (u == 0xffffffff) /* do something */

int i = hex_literal;
unsigned u;
memcpy (&u, &i, sizeof (u));
if (i == u) /* do something */
if ((i & 0x7fffffff) == (u & 0x7fffffff)) /* do something */

int i = hex_literal;
unsigned u = i;
if (i == u) /* do something */

unsigned u = hex_literal;
int i = u;
if (i == u) /* do something */

int i = hex_literal;
unsigned u = hex_literal;
if (i == hex_literal && u == hex_literal) /* do something */

char c = 0xff;
if (c >> 4 == 0xf) /* do something */

signed char c = 0xff;
if (((c >> 4) & 0xff) == 0xf) /* do something */

Solution

  • I will make the added assumption that no types have padding bits on the implementation under discussion. Let's take them one at a time:

    unsigned u = 0xffffffff;
    if (u == 4294967295) /* do something */
    

    Yes.

    int i = 0xffffffff;
    if (i == -1) /* do something */
    

    No. Conversion of an out-of-range number to a signed type gives an implementation-defined result.

    unsigned u = (int)0xffffffff;
    if (u == 0xffffffff) /* do something */
    

    No, same reason as the previous example.

    int i = hex_literal;
    unsigned u;
    memcpy (&u, &i, sizeof (u));
    if (i == u) /* do something */
    if ((i & 0x7fffffff) == (u & 0x7fffffff)) /* do something */
    

    Yes. The standard guarantees that each value bit in a signed type has the same value in the object representation of the corresponding unsigned type.

    int i = hex_literal;
    unsigned u = i;
    if (i == u) /* do something */
    

    Yes. The promotion of i from int to unsigned is deterministic and produces the same value both in the assignment to u and in the comparison.

    unsigned u = hex_literal;
    int i = u;
    if (i == u) /* do something */
    

    Yes, but only if hex_literal is in the range of (positive) values representable by an int - otherwise the implementation-defined result strikes again.

    int i = hex_literal;
    unsigned u = hex_literal;
    if (i == hex_literal && u == hex_literal) /* do something */
    

    u == hex_literal will always evalulate to true, but i == hex_literal need only do so if hex_literal is in the range of values representable by an int.

    char c = 0xff;
    if (c >> 4 == 0xf) /* do something */
    

    char may be signed or unsigned. If it is unsigned then the test will be true; if signed, then c and c >> 4 will have implementation-defined values, so it may not be true.

    signed char c = 0xff;
    if (((c >> 4) & 0xff) == 0xf) /* do something */
    

    c will have an implementation-defined value, so the test may not be true.

    Note that all of your questions other than the memcpy() one pertain only to the values rather than the representation.