[Warning] Signed mistach for basic datatype.

Discussion in 'C Programming' started by umesh.kalappa0, Dec 6, 2013.

  1. Hi All ,

    The below sample caught my attention i.e

    int a ;
    unsigned int b;
    int func()
    return a =b;
    the compiler didn't warn me about the signed mismatch in the above case.
    where as

    int *a ;
    unsigned int *b;
    int func()
    a =b;
    return *a;
    compiler warns me as

    warning: pointer targets in assignment differ in signedness [-Wpointer-sign]

    I’m bit confused or i'm missing something here .

    any thoughts ??

    umesh.kalappa0, Dec 6, 2013
    1. Advertisements

  2. In most cases, the language standard defines a construct in terms of
    syntax, constraints and semantics. A diagnostic is required in the case
    of a constraint violation, but a compiler may also warn about other
    things if it likes.

    The first case meets all the constraints (so no diagnostic is required)
    and the assignment proceeds by converting the value of the right operand
    to the type of the left operand. This conversion is not entirely safe,
    but the compiler is not obliged to tell you about it. You may, however,
    be able to ask for such a warning. For example, if you are using gcc or
    clang, you can do so by adding -Wsign-conversion to the compile command.

    In the second case, the assignment does not meet the constraints, so a
    diagnostic *is* required. The description of the constraints is not
    easy to follow[1] but the gist of it that the two pointers should be
    pointers to compatible types, but 'int' and 'unsigned int' are not. The
    rules for what constitute compatible types are rather detailed, but to a
    first approximation, 'compatible type' means 'the same type'.

    [1] Here are the C11 constraints specific to simple assignments:

    -- the left operand has atomic, qualified, or unqualified arithmetic
    type, and the right has arithmetic type;

    -- the left operand has an atomic, qualified, or unqualified version of
    a structure or union type compatible with the type of the right;

    -- the left operand has atomic, qualified, or unqualified pointer type,
    and (considering the type the left operand would have after lvalue
    conversion) both operands are pointers to qualified or unqualified
    versions of compatible types, and the type pointed to by the left has
    all the qualifiers of the type pointed to by the right;

    -- the left operand has atomic, qualified, or unqualified pointer type,
    and (considering the type the left operand would have after lvalue
    conversion) one operand is a pointer to an object type, and the other
    is a pointer to a qualified or unqualified version of void, and the
    type pointed to by the left has all the qualifiers of the type
    pointed to by the right;

    -- the left operand is an atomic, qualified, or unqualified pointer, and
    the right is a null pointer constant; or

    -- the left operand has type atomic, qualified, or unqualified _Bool,
    and the right is a pointer.
    Ben Bacarisse, Dec 6, 2013
    1. Advertisements

  3. On most machines, there is no actual "conversion" done. That is, the
    bits are copied. (A convenience of twos complement.)

    Since unsigned arithmetic is modulo 2**(number of bits), on a ones
    complement or sign magnitude machine some actual conversion would
    need to be done.
    In this case, no conversion of the values can be done. On twos
    complement machines, you are likely to get the expected value, but, as
    far as I know it, machines could still store the bits differently for
    unsigned and signed. One might be big-endian, the other little endian,
    as an example. Or the padding could be done differently.

    On ones complement or sign magnitude machines, you will get the wrong
    value when the signed value goes negative, even if the bits are stored
    in the same order.


    -- glen
    glen herrmannsfeldt, Dec 6, 2013
  4. The way I'd put it is that a conversion is always done, but in some
    cases the conversion is trivial, not changing the representation.

    The difference between the two cases it that assignment does an
    implicit conversion between any two numeric types, but not between
    pointer types. Arithmetic conversion converts a value of one type
    to the same mathematical value represented in another type.

    But there are no implicit conversions between distinct pointer types.
    Such a conversion lets you treat the pointed-to object that's of
    some time *as if* it were an object of some other type. You can do
    that, but it's dangerous enough that the language won't let you do
    it implicitly. (Almost) all pointer conversions involving distinct
    pointer types require a cast.

    Keith Thompson, Dec 6, 2013
  5. (snip, and previous snip, regarding conversions between signed and
    unsigned integer types)
    Sounds fine to me. But after a while, people get used to that and
    forget that they are actually different types.

    For me, I think I often ignore the conversion for char vs.
    unsigned char, but not the other integer types.
    I am not sure by now how much difference is allowed between the signed
    and unsigned types of the same integer type.
    -- glen
    glen herrmannsfeldt, Dec 6, 2013
  6. umesh.kalappa0

    James Kuyper Guest

    On 12/06/2013 03:20 PM, glen herrmannsfeldt wrote:
    The question is meaningful only for values that are within the common
    range of the two types. For values within that common range, no
    difference is allowed, at all (6.2.5p9).
    James Kuyper, Dec 6, 2013
  7. That allows for twos complement, ones complement, and sign magnitude to
    use the same bits, but represent different negative values.

    Is the unsigned type of the corresponding signed type allowed to have
    fewer bits? More specifically, can the unsigned type be only the
    non-negative values from the signed type?

    A processor that only did signed ones complement or sign magnitude
    could then use only the non-negative values for its unsigned, with
    one padding bit where the sign bit would go.

    Processors like the 7090 stored sign magnitude 16 bit (15 plus sign)
    integers in 36 bit words. Floating point used the whole word.
    I believe, but didn't look it up, that the sign bit is not adjacent
    to the value bits. Unsigned int would most natually have 15 bits,
    and signed 16 (with sign).

    But I don't know that there ever was a C compiler for the 7090.

    -- glen
    glen herrmannsfeldt, Dec 6, 2013
  8. umesh.kalappa0

    James Kuyper Guest

    Yes, there could be as many as three different signed types that differ
    from each other only in how they interpreted the sign bit. However, each
    of them must have its own unique "corresponding unsigned type".
    (6.2.5p6) For instance, they could be long, int, and short,
    respectively, all with 32 bits. Or two of them could be extended integer
    types with names from the name space reserved to the implementation like
    __int1c and __intsm, with int itself being the 2's complement type.
    The two types have to have exactly the same size. However, the bits in a
    signed type can be broken down into padding, sign, and value bits.
    "The range of nonnegative values of a signed integer type is a subrange
    of the corresponding unsigned integer type, ..." (6.2.5p9)
    That would not be possible if the unsigned type had fewer value bits
    than the signed type.
    Yes. In that case, the unsigned type has precisely the same number of
    value bits as the signed type, and that is allowed.
    James Kuyper, Dec 6, 2013
  9. umesh.kalappa0

    Tim Rentsch Guest

    Actually there can be as many as six different signed types whose
    value bits all match, presuming of course padding bits. (And
    technically what is being referenced here is type representations,
    not types, as there may be an arbitrary number of distinct signed
    types all of whose value bits match, even if they all use, eg,
    two's complement. It might be reasonable, for example, to give
    each 'enum' type its own extended integer type, distinct from
    'int', even though they all use the same representation as 'int'.)
    Tim Rentsch, Dec 19, 2013
  10. umesh.kalappa0

    Tim Rentsch Guest

    The first sentence is nonsense, because the representation of the
    non-negative values of the signed type has implications both for
    the negative values of the signed type, and for any larger values
    of the unsigned type, due to the restrictions on how integer
    types may be represented.
    Tim Rentsch, Dec 19, 2013
  11. umesh.kalappa0

    Tim Rentsch Guest

    There may be variation only in padding bits. If there are no
    padding bits, the representation of a signed type completely
    determines the representation of the corresponding unsigned type,
    and the representation of an unsigned type completely determines
    the representation of the corresponding signed type, except for
    the choice of the three different ways negative values can be
    represented, and whether the signed type does or does not have a
    (single) trap representation. (There also are some limitations
    on what can happen when padding bits are in the picture, but I
    will leave that for interested readers to look up themselves.)
    Tim Rentsch, Dec 20, 2013
  12. The specific case I was interested in was where the unsigned type
    has a padding bit in the place where the signed type has a sign bit,
    all other bits being the same (padding bits). That would be
    convenient for a processor with no unsigned operations.
    (It would still have to treat the overflow case properly.)

    -- glen
    glen herrmannsfeldt, Dec 20, 2013
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.