Passing different type

Y

Yoshi

Hello, I'm passing int value to the function that takes unsigned int.
But whenn I compile following code, there is no warning. How come?

#include <stdio.h>

void test(unsigned int i){
printf("value:%d\n", i);
}

int main(void)
{
int i = -3;
test(i);
return 0;
}

Thank you
 
I

Ike Naar

Hello, I'm passing int value to the function that takes unsigned int.

Actually, you're not; the int value is implicitly converted to
unsigned int, by taking the value modulo (UINT_MAX+1), and then
the unsigned value is passed to the function.
But whenn I compile following code, there is no warning. How come?

#include <stdio.h>

void test(unsigned int i){
printf("value:%d\n", i);

Since i is an unsigned int, you should use the %u format here.
The compiler is not required to issue a diagnostic for this.
}

int main(void)
{
int i = -3;
test(i);

So here the value of the argument expression (-3) is implicitly converted
to UINT_MAX+1-3 (typically 4294967293 on a 32-bit machine) and the result
is passed to test().
 
B

Ben Bacarisse

Yoshi said:
Hello, I'm passing int value to the function that takes unsigned int.
But whenn I compile following code, there is no warning. How come?

You are probably not asking for one. I get one:

xx.c: In function ‘main’:
xx.c:10: warning: conversion to ‘unsigned int’ from ‘int’ may change the
sign of the result

(In gcc it's -Wconversion that gets you this.)

You have to ask because the code you show is perfectly valid (though I'd
print an unsigned int with %u rather than %d). Did you expect a
diagnostic meassage because you thought the code had an error that
needed to be diagnosed?
 
D

Denis McMahon

Hello, I'm passing int value to the function that takes unsigned int.
But whenn I compile following code, there is no warning. How come?

#include <stdio.h>

void test(unsigned int i){
printf("value:%d\n", i);
}

int main(void)
{
int i = -3;
test(i);
return 0;
}

Thank you

$ gcc -Wconversion test21.c -o t21
test21.c: In function ‘main’:
test21.c:11: warning: conversion to ‘unsigned int’ from ‘int’ may change
the sign of the result
$

I would guess that maybe it's a warning you need to enable?

It seems that none of "-pedantic -Wall -Wextra" will give this warning.

Other issues have been mentioned elsewhere. I tried to find a warning
that would alert to the use of %d in a format specifier for an unsigned
int, but I can't find one - one of the gurus might be able to suggest one.

Rgds

Denis McMahon
 
Y

Yoshi

$ gcc -Wconversion test21.c -o t21
test21.c: In function ‘main’:
test21.c:11: warning: conversion to ‘unsigned int’ from ‘int’ may change
the sign of the result
$

I would guess that maybe it's a warning you need to enable?

It seems that none of "-pedantic -Wall -Wextra" will give this warning.

Other issues have been mentioned elsewhere. I tried to find a warning
that would alert to the use of %d in a format specifier for an unsigned
int, but I can't find one - one of the gurus might be able to suggest one..

Rgds

Denis McMahon


Thank you for answers, I was misunderstanding that -Wall should cover
all warnings, and also thinking that it is not valid(it only works
under some circumstances).
Now I understand that in this case, as folks said, the conversion from
signed int to int is defined and valid in C.

So let me ask my understanding about conversion once more:

In the following code,
(1) i = c + 1; // c + 1 is converted int, so UCHAR_MAX + 1 becomes
int, valid?
(2) i = ++c; // i = (c = c + 1), this is undefined ?
(3) i = j + 1; // j + 1 cannot be expressed by i so undefined?
(4) i = ++j; // i = (j = j + 1), j + 1 cannot be expressed by j, so
undefined?


#include <stdio.h>
#include <limits.h>


int main(void)
{
int i;
unsigned int j = UINT_MAX;
unsigned char c = UCHAR_MAX;

i = c + 1;
printf("i=%d\n", i);
i = ++c;
printf("i=%d\n", i);

i = j + 1;
printf("i=%d\n", i);
i = ++j;
printf("i=%d\n", i);

return 0;
}
 
B

Ben Bacarisse

Yoshi said:
Thank you for answers, I was misunderstanding that -Wall should cover
all warnings, and also thinking that it is not valid(it only works
under some circumstances).
Now I understand that in this case, as folks said, the conversion from
signed int to int is defined and valid in C.

Presumably you mean "signed int to *unsigned* int". int is the same as
signed int in almost all situations.
So let me ask my understanding about conversion once more:

Here are the declarations moved up to help read this in order:

| int i;
| unsigned int j = UINT_MAX;
| unsigned char c = UCHAR_MAX;
In the following code,
(1) i = c + 1; // c + 1 is converted int, so UCHAR_MAX + 1 becomes
int, valid?

'c + 1' is already an int so it is not converted. 'c' is converted to
int before the addition. This is part of what C calls the "usual
arithmetic conversions". So, 'c' gets converted to int and one is added
to that. The result is put in 'i' with no further conversion. When
UCHAR_MAX is 255, 'i' gets the value 256.

By the way, all of this discussion is about the normal situation where
UCHAR_MAX is <= INT_MAX. On some peculiar systems, the rules can
produce different results.
(2) i = ++c; // i = (c = c + 1), this is undefined ?

No, it's fine. In this case, when c is UCHAR_MAX the result in 'i' is
0. I could tell you why, but you might learn more by trying to work out
why for yourself. Let me know (well, let the group know) if you are
unsure.
(3) i = j + 1; // j + 1 cannot be expressed by i so undefined?

No, this too is fine (in the exact case you are asking about). First
you need to know that j is not converted to an int but, instead, 1 is
converted to unsigned int. Unsigned arithmetic does not overflow, it
"wraps round" so 'j + 1' is 0 when 'j' is UINT_MAX and this unsigned int
result can be represented in 'i' so the conversion to int and subsequent
assignment is valid.

Had 'j' been UINT_MAX-1 to start with, the conversion of 'j + 1' to int
would have been either implementation defined or an implementation
defined signal would be raised.
(4) i = ++j; // i = (j = j + 1), j + 1 cannot be expressed by j, so
undefined?

Again, that's fine.

<snip>
 
Y

Yoshi

Presumably you mean "signed int to *unsigned* int". int is the same as
signed int in almost all situations.

Thanks Ben, Yes, I meant it, sorry for the typo.
Here are the declarations moved up to help read this in order:

| int i;
| unsigned int j = UINT_MAX;
| unsigned char c = UCHAR_MAX;


'c + 1' is already an int so it is not converted. 'c' is converted to
int before the addition. This is part of what C calls the "usual
arithmetic conversions". So, 'c' gets converted to int and one is added
to that. The result is put in 'i' with no further conversion. When
UCHAR_MAX is 255, 'i' gets the value 256.
OK.


By the way, all of this discussion is about the normal situation where
UCHAR_MAX is <= INT_MAX. On some peculiar systems, the rules can
produce different results.


No, it's fine. In this case, when c is UCHAR_MAX the result in 'i' is
0. I could tell you why, but you might learn more by trying to work out
why for yourself. Let me know (well, let the group know) if you are
unsure.

OK, let me try.

++c is equal to c = c + 1, and 'c' is converted to int. So when
UCHAR_MAX is 255, 'c + 1' is 256, which is int. Then int value of 256
is assigned to 'c',
which is unsigned char.

When I look into '6.3.1.3 Signed and unsigned integers', it says that
'if a value
with integer type is converted to another integer type and the value
cannot be
represented by the new type, and if the new type is unsigned value,
the value is
converted by repeatedly adding or subtracting one more than the
maximum value
that can be represented in the new type until the value is in the
range of the new type.'

I think above sentence is not clear enough, but I found following way
to convert in other place(which is the book written in non-English).
If there is clearer description of converston rules in C specification
document, please tell me.


So 256 ,which is signed int cannot be represented by the unsigned
char, therefore 256 % (1 + UCHAR_MAX) = 0 in this case.

Other than that, what I found for signed/unsigned integer conversion
rules are followings:

(1)From signed X to signed Y
X <= Y x

X > Y if x can be represented by signed Y, then x
if x cannot be represented by signed Y, then
undefined

(2)From unsigned X to signed Y
X < Y x

X >= Y if x can be represented by signed Y, then x
if x cannot be represented by signed Y, then
undefined

(3)From signed X to unsigned Y
X < Y when value of X >= 0, then x
when value of X < 0, then (signed Y)x + (1 +
Y_MAX)

X == Y when value of x >= 0, then x
when value of X < 0, then x + (1 + Y_MAX)

X > Y when value of x >= 0, then x % (1 + Y_MAX)
when value of X < 0, then (1 + Y_MAX) - (-x %
(1 + Y_MAX))

(4)From unsigned X to unsigned Y
X <= Y x

X > Y x % (1 + Y_MAX)

If above from (1) to (4) are correct, there are 2 cases that can be
undefined.

One is the case like following case:

int i = INT_MAX;
char c;
c = i;

The Other is the case like following:
unsigned int i = UINT_MAX;
char c;
c = i;

No, this too is fine (in the exact case you are asking about). First
you need to know that j is not converted to an int but, instead, 1 is
converted to unsigned int. Unsigned arithmetic does not overflow, it
"wraps round" so 'j + 1' is 0 when 'j' is UINT_MAX and this unsigned int
result can be represented in 'i' so the conversion to int and subsequent
assignment is valid.

I see, I did not know that UINT_MAX + 1 becomes legally 0.

Had 'j' been UINT_MAX-1 to start with, the conversion of 'j + 1' to int
would have been either implementation defined or an implementation
defined signal would be raised.


Again, that's fine.

OK, then j + 1 becomes 0, so j becomes 0 and assigned to i.

Thank you
 
B

Ben Bacarisse

Yoshi said:
OK, let me try.

++c is equal to c = c + 1, and 'c' is converted to int. So when
UCHAR_MAX is 255, 'c + 1' is 256, which is int. Then int value of 256
is assigned to 'c',
which is unsigned char.
Yes.

When I look into '6.3.1.3 Signed and unsigned integers', it says that

'if a value with integer type is converted to another integer type and
the value cannot be represented by the new type, and if the new type
is unsigned value, the value is converted by repeatedly adding or
subtracting one more than the maximum value that can be represented in
the new type until the value is in the range of the new type.'

I think above sentence is not clear enough, but I found following way
to convert in other place(which is the book written in non-English).
If there is clearer description of converston rules in C specification
document, please tell me.

I find it clear enough, but another way to describe it is that the
result for converting S is smallest positive R such that R = S mod
T_MAX + 1 (where T_MAX is the largest number representable in the target
type).
So 256 ,which is signed int cannot be represented by the unsigned
char, therefore 256 % (1 + UCHAR_MAX) = 0 in this case.

Yes, though this can't use C's % operator to describe the result or you
get a circular definition -- the usual arithmetic conversions are
applied to the operands of %.
Other than that, what I found for signed/unsigned integer conversion
rules are followings:

(1)From signed X to signed Y
X <= Y x

X > Y if x can be represented by signed Y, then x
if x cannot be represented by signed Y, then
undefined

(2)From unsigned X to signed Y
X < Y x

X >= Y if x can be represented by signed Y, then x
if x cannot be represented by signed Y, then
undefined

(3)From signed X to unsigned Y
X < Y when value of X >= 0, then x
when value of X < 0, then (signed Y)x + (1 +
Y_MAX)

X == Y when value of x >= 0, then x
when value of X < 0, then x + (1 + Y_MAX)

X > Y when value of x >= 0, then x % (1 + Y_MAX)
when value of X < 0, then (1 + Y_MAX) - (-x %
(1 + Y_MAX))

(4)From unsigned X to unsigned Y
X <= Y x

X > Y x % (1 + Y_MAX)

Sorry, but I don't understand this at all. In particular I don't know
what you mean by X < Y and so on. If X and Y are types, what does the
ordering mean (is it conversion rank?) and if X and Y are values rather
than types, how do you know the ordering when the conversion is
undefined?

I am suspicious that you've got it right because the conversion to an
unsigned type does not need to distinguish between (3) and (4) and your
case (3) seems way too complex even though I don't really know what it
means.
If above from (1) to (4) are correct, there are 2 cases that can be
undefined.

One is the case like following case:

int i = INT_MAX;
char c;
c = i;

Ah, no, not always. char can be an unsigned type so the conversion is
well-defined. Had you defined c as unsigned char, you'd be right
in the "normal" case where INT_MAX > SCHAR_MAX.
The Other is the case like following:
unsigned int i = UINT_MAX;
char c;
c = i;

See above. But why distinguish these two cases? Surely it is simpler
just to say the conversion to a signed integer type is undefined when
the value cannot be represented in the target type.

<snip>
 
Y

Yoshi

I find it clear enough, but another way to describe it is that the
result for converting S is smallest positive R such that R = S mod
T_MAX + 1 (where T_MAX is the largest number representable in the target
type).

Thanks, it makes sense for me.

Yes, though this can't use C's % operator to describe the result or you
get a circular definition -- the usual arithmetic conversions are
applied to the operands of %.

OK, so I should have written 256 mod (1 + UCHAR_MAX) becomes 0.

Sorry, but I don't understand this at all. In particular I don't know
what you mean by X < Y and so on. If X and Y are types, what does the
ordering mean (is it conversion rank?) and if X and Y are values rather
than types, how do you know the ordering when the conversion is
undefined?

I was thinking X and Y as type and ordering was conversion rank, and x
as value of X. But never mind, sorry, I was confused about these cases
and trying to sort it out all cases.
I am suspicious that you've got it right because the conversion to an
unsigned type does not need to distinguish between (3) and (4) and your
case (3) seems way too complex even though I don't really know what it
means.




Ah, no, not always. char can be an unsigned type so the conversion is
well-defined. Had you defined c as unsigned char, you'd be right
in the "normal" case where INT_MAX > SCHAR_MAX.

OK, I should have written 'signed char c;', and INT_MAX > SCHAR_MAX to
describe undefined case.

See above. But why distinguish these two cases? Surely it is simpler
just to say the conversion to a signed integer type is undefined when
the value cannot be represented in the target type.

You're right, there is no need to distinguish these cases.
So with your help, my understanding about integer conversion is now
following:

(1) If original value can be represented by the target type, value is
unchanged.
(2) Otherwise, if the target type is unsigned integer type, then the
result is (original value) mod (T_MAX + 1), where T_MAX is the maximum
value of the target type.
(3) Otherwise, the target type is signed integer type, and result is
undefined.


Thank you
 
B

Ben Bacarisse

Yoshi said:
So with your help, my understanding about integer conversion is now
following:

(1) If original value can be represented by the target type, value is
unchanged.
(2) Otherwise, if the target type is unsigned integer type, then the
result is (original value) mod (T_MAX + 1), where T_MAX is the maximum
value of the target type.
(3) Otherwise, the target type is signed integer type, and result is
undefined.

Yes, except that it's not really undefined. It's about as bad as you
can get without being undefined so I it probably helps to think of it as
undefined. I think I made that point earlier in the thread but it might
have been somewhere else. Rather than repeat it, this is what the
standard says:

6.3.1.3 Signed and unsigned integers

1 When a value with integer type is converted to another integer type
other than _Bool, if the value can be represented by the new type,
it is unchanged.

2 Otherwise, if the new type is unsigned, the value is converted by
repeatedly adding or subtracting one more than the maximum value
that can be represented in the new type until the value is in the
range of the new type.

3 Otherwise, the new type is signed and the value cannot be
represented in it; either the result is implementation-defined or an
implementation-defined signal is raised.

So not quite UB, but any assumption you make about what happens might be
wrong tomorrow or the next day.
 
Y

Yoshi

Yes, except that it's not really undefined.  It's about as bad as you
can get without being undefined so I it probably helps to think of it as
undefined.  I think I made that point earlier in the thread but it might
have been somewhere else.  Rather than repeat it, this is what the
standard says:

  6.3.1.3 Signed and unsigned integers

  1 When a value with integer type is converted to another integer type
    other than _Bool, if the value can be represented by the new type,
    it is unchanged.

  2 Otherwise, if the new type is unsigned, the value is converted by
    repeatedly adding or subtracting one more than the maximum value
    that can be represented in the new type until the value is in the
    range of the new type.

  3 Otherwise, the new type is signed and the value cannot be
    represented in it; either the result is implementation-defined or an
    implementation-defined signal is raised.

So not quite UB, but any assumption you make about what happens might be
wrong tomorrow or the next day.

Thanks Ben, integer conversion was not clear for me, but It has become
much clearer now.
 

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,954
Messages
2,570,116
Members
46,704
Latest member
BernadineF

Latest Threads

Top