[Warning] Signed mistach for basic datatype.

U

umesh.kalappa0

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

Thanks
~Umesh
 
B

Ben Bacarisse

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 .

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

glen herrmannsfeldt

Ben Bacarisse said:
(e-mail address removed) writes:
(snip)
int a ;
unsigned int b; (snip)
return a =b;
(snip)
int *a ;
unsigned int *b;
int func()
{
a =b;
return *a;
(snip)
warning: pointer targets in assignment differ in
signedness [-Wpointer-sign]
I???m bit confused or i'm missing something here .
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.

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

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.

(snip)

-- glen
 
K

Keith Thompson

glen herrmannsfeldt said:
Ben Bacarisse said:
(e-mail address removed) writes:
(snip)
int a ;
unsigned int b; (snip)
return a =b;
(snip)
int *a ;
unsigned int *b;
int func()
{
a =b;
return *a;
(snip)
warning: pointer targets in assignment differ in
signedness [-Wpointer-sign]
I???m bit confused or i'm missing something here .
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.

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.

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.

[...]
 
G

glen herrmannsfeldt

(snip, and previous snip, regarding conversions between signed and
unsigned integer types)
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.

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

I am not sure by now how much difference is allowed between the signed
and unsigned types of the same integer 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.

-- glen
 
J

James Kuyper

On 12/06/2013 03:20 PM, glen herrmannsfeldt wrote:
....
I am not sure by now how much difference is allowed between the signed
and unsigned types of the same integer type.

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

glen herrmannsfeldt

James Kuyper said:
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).

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
 
J

James Kuyper

That allows for twos complement, ones complement, and sign magnitude to
use the same bits, but represent different negative values.

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.
Is the unsigned type of the corresponding signed type allowed to have
fewer bits?

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.
... More specifically, can the unsigned type be only the
non-negative values from 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.
 
T

Tim Rentsch

James Kuyper said:
That allows for twos complement, ones complement, and sign
magnitude to use the same bits, but represent different negative
values.

Yes, there could be as many as three different signed types that
differ from each other only in how they interpreted the sign bit.
[snip elaboration]

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'.)
 
T

Tim Rentsch

James Kuyper said:
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).

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

Tim Rentsch

glen herrmannsfeldt said:
I am not sure by now how much difference is allowed between the
signed and unsigned types of the same integer type.

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

glen herrmannsfeldt

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

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
 

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. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top