Why is the sign different after subtracting unsigned and signed?
Clash Royale CLAN TAG#URR8PPP
up vote
24
down vote
favorite
unsigned int t = 10;
int d = 16;
float c = t - d;
int e = t - d;
Why is the value of c
positive but e
negative?
c++ language-lawyer unsigned negative-number
New contributor
add a comment |Â
up vote
24
down vote
favorite
unsigned int t = 10;
int d = 16;
float c = t - d;
int e = t - d;
Why is the value of c
positive but e
negative?
c++ language-lawyer unsigned negative-number
New contributor
2
Most compilers have an option to warn you if you're implicitly converting asigned
value tounsigned
or vice versa. On GCC and Clang, this is-Wconversion
. Your question is a good example of why it's a good idea to compile with that.
â Davislor
5 hours ago
add a comment |Â
up vote
24
down vote
favorite
up vote
24
down vote
favorite
unsigned int t = 10;
int d = 16;
float c = t - d;
int e = t - d;
Why is the value of c
positive but e
negative?
c++ language-lawyer unsigned negative-number
New contributor
unsigned int t = 10;
int d = 16;
float c = t - d;
int e = t - d;
Why is the value of c
positive but e
negative?
c++ language-lawyer unsigned negative-number
c++ language-lawyer unsigned negative-number
New contributor
New contributor
edited 7 mins ago
Rishav
2,3241230
2,3241230
New contributor
asked 10 hours ago
Eugene Kolombet
1213
1213
New contributor
New contributor
2
Most compilers have an option to warn you if you're implicitly converting asigned
value tounsigned
or vice versa. On GCC and Clang, this is-Wconversion
. Your question is a good example of why it's a good idea to compile with that.
â Davislor
5 hours ago
add a comment |Â
2
Most compilers have an option to warn you if you're implicitly converting asigned
value tounsigned
or vice versa. On GCC and Clang, this is-Wconversion
. Your question is a good example of why it's a good idea to compile with that.
â Davislor
5 hours ago
2
2
Most compilers have an option to warn you if you're implicitly converting a
signed
value to unsigned
or vice versa. On GCC and Clang, this is -Wconversion
. Your question is a good example of why it's a good idea to compile with that.â Davislor
5 hours ago
Most compilers have an option to warn you if you're implicitly converting a
signed
value to unsigned
or vice versa. On GCC and Clang, this is -Wconversion
. Your question is a good example of why it's a good idea to compile with that.â Davislor
5 hours ago
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
41
down vote
Let's start by analysing the result of t - d
.
t
is an unsigned int
while d
is an int
, so to do arithmetic on them, the value of d
is converted to an unsigned int
(C++ rules say unsigned gets preference here). So we get 10u - 16u
, which (assuming 32-bit int
) wraps around to 4294967290u
.
This value is then converted to float
in the first declaration, and to int
in the second one.
Assuming the typical implementation of float
(32-bit single-precision IEEE), its highest representable value is roughly 1e38
, so 4294967290u
is well within that range. There will be rounding errors, but the conversion to float won't overflow.
For int
, the situation's different. 4294967290u
is too big to fit into an int
, so wrap-around happens and we arrive back at the value -6
. Note that such wrap-around is not guaranteed by the standard: the resulting value in this case is implementation-defined(1), which means it's up to the compiler what the result value is, but it must be documented.
(1) C++17 (N4659), [conv.integral] 7.8/3:
If the destination type is signed, the value is unchanged if it can be represented in the destination type;
otherwise, the value is implementation-defined.
Just curious, but does in this case implementation-defined means hardware related? Since, most common hardware is two's-complement, you got this behavior, but it would change on a ones-complement CPU even using the same compiler?
â user1810087
9 hours ago
3
@user1810087 It means that the compiler must document what will happen, which means the compiler authors must think about what will happen, and implement it consistently (or at least document it consistently with implementation). It's quite likely their decision will be influenced by the target HW, and so the documentation of this will be platform-specific.
â Angew
9 hours ago
1
It's not behavior which is implementation-defined â only value (see your own footnote). In particular, implementation can't throw an exception, raise a signal etc. due to such conversion.
â Ruslan
7 hours ago
@Ruslan Very good point, thans. Answer edited.
â Angew
6 hours ago
add a comment |Â
up vote
12
down vote
First, you have to understand "usual arithmetic conversions" (that link is for C, but the rules are the same in C++). In C++, if you do arithmetic with mixed types (you should avoid that when possible, by the way), there's a set of rules that decides which type the calculation is done in.
In your case, you are subtracting a signed int from an unsigned int. The promotion rules say that the actual calculation is done using unsigned int
.
So your calculation is 10 - 16
in unsigned int arithmetic. Unsigned arithmetic is modulo arithmetic, meaning that it wraps around. So, assuming your typical 32-bit int, the result of this calculation is 2^32 - 6.
This is the same for both lines. Note that the subtraction is completely independent from the assignment; the type on the left side has absolutely no influence on how the calculation happens. It is a common beginner mistake to think that the type on the left side somehow influences the calculation; but float f = 5 / 6
is zero, because the division still uses integer arithmetic.
The difference, then, is what happens during the assignment. The result of the subtraction is implicitly converted to float
in one case, and int
in the other.
The conversion to float tries to find the closest value to the actual one that the type can represent. This will be some very large value; not quite the one the original subtraction yielded though.
The conversion to int says that if the value fits into the range of int, the value will be unchanged. But 2^32 - 6 is far larger than the 2^31 - 1 that a 32-bit int can hold, so you get the other part of the conversion rule, which says that the resulting value is implementation-defined. This is a term in the standard that means "different compilers can do different things, but they have to document what they do".
For all practical purposes, all compilers that you'll likely encounter say that the bit pattern stays the same and is just interpreted as signed. Because of the way 2's complement arithmetic works (the way that almost all computers represent negative numbers), the result is the -6 you would expect from the calculation.
But all this is a very long way of repeating the first point, which is "don't do mixed type arithmetic". Cast the types first, explicitly, to types that you know will do the right thing.
I think you meant2^31-1
for your second value in paragraph 7. Because "2^32 - 6 is far larger than the 2^32 - 1" doesn't, on the face of it, seem an obvious thing to assert. Most people would think that the first was exactly 5 less than the second, not far larger :-)
â Damien_The_Unbeliever
7 hours ago
@Damien_The_Unbeliever Fixed, thanks.
â Sebastian Redl
4 hours ago
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
41
down vote
Let's start by analysing the result of t - d
.
t
is an unsigned int
while d
is an int
, so to do arithmetic on them, the value of d
is converted to an unsigned int
(C++ rules say unsigned gets preference here). So we get 10u - 16u
, which (assuming 32-bit int
) wraps around to 4294967290u
.
This value is then converted to float
in the first declaration, and to int
in the second one.
Assuming the typical implementation of float
(32-bit single-precision IEEE), its highest representable value is roughly 1e38
, so 4294967290u
is well within that range. There will be rounding errors, but the conversion to float won't overflow.
For int
, the situation's different. 4294967290u
is too big to fit into an int
, so wrap-around happens and we arrive back at the value -6
. Note that such wrap-around is not guaranteed by the standard: the resulting value in this case is implementation-defined(1), which means it's up to the compiler what the result value is, but it must be documented.
(1) C++17 (N4659), [conv.integral] 7.8/3:
If the destination type is signed, the value is unchanged if it can be represented in the destination type;
otherwise, the value is implementation-defined.
Just curious, but does in this case implementation-defined means hardware related? Since, most common hardware is two's-complement, you got this behavior, but it would change on a ones-complement CPU even using the same compiler?
â user1810087
9 hours ago
3
@user1810087 It means that the compiler must document what will happen, which means the compiler authors must think about what will happen, and implement it consistently (or at least document it consistently with implementation). It's quite likely their decision will be influenced by the target HW, and so the documentation of this will be platform-specific.
â Angew
9 hours ago
1
It's not behavior which is implementation-defined â only value (see your own footnote). In particular, implementation can't throw an exception, raise a signal etc. due to such conversion.
â Ruslan
7 hours ago
@Ruslan Very good point, thans. Answer edited.
â Angew
6 hours ago
add a comment |Â
up vote
41
down vote
Let's start by analysing the result of t - d
.
t
is an unsigned int
while d
is an int
, so to do arithmetic on them, the value of d
is converted to an unsigned int
(C++ rules say unsigned gets preference here). So we get 10u - 16u
, which (assuming 32-bit int
) wraps around to 4294967290u
.
This value is then converted to float
in the first declaration, and to int
in the second one.
Assuming the typical implementation of float
(32-bit single-precision IEEE), its highest representable value is roughly 1e38
, so 4294967290u
is well within that range. There will be rounding errors, but the conversion to float won't overflow.
For int
, the situation's different. 4294967290u
is too big to fit into an int
, so wrap-around happens and we arrive back at the value -6
. Note that such wrap-around is not guaranteed by the standard: the resulting value in this case is implementation-defined(1), which means it's up to the compiler what the result value is, but it must be documented.
(1) C++17 (N4659), [conv.integral] 7.8/3:
If the destination type is signed, the value is unchanged if it can be represented in the destination type;
otherwise, the value is implementation-defined.
Just curious, but does in this case implementation-defined means hardware related? Since, most common hardware is two's-complement, you got this behavior, but it would change on a ones-complement CPU even using the same compiler?
â user1810087
9 hours ago
3
@user1810087 It means that the compiler must document what will happen, which means the compiler authors must think about what will happen, and implement it consistently (or at least document it consistently with implementation). It's quite likely their decision will be influenced by the target HW, and so the documentation of this will be platform-specific.
â Angew
9 hours ago
1
It's not behavior which is implementation-defined â only value (see your own footnote). In particular, implementation can't throw an exception, raise a signal etc. due to such conversion.
â Ruslan
7 hours ago
@Ruslan Very good point, thans. Answer edited.
â Angew
6 hours ago
add a comment |Â
up vote
41
down vote
up vote
41
down vote
Let's start by analysing the result of t - d
.
t
is an unsigned int
while d
is an int
, so to do arithmetic on them, the value of d
is converted to an unsigned int
(C++ rules say unsigned gets preference here). So we get 10u - 16u
, which (assuming 32-bit int
) wraps around to 4294967290u
.
This value is then converted to float
in the first declaration, and to int
in the second one.
Assuming the typical implementation of float
(32-bit single-precision IEEE), its highest representable value is roughly 1e38
, so 4294967290u
is well within that range. There will be rounding errors, but the conversion to float won't overflow.
For int
, the situation's different. 4294967290u
is too big to fit into an int
, so wrap-around happens and we arrive back at the value -6
. Note that such wrap-around is not guaranteed by the standard: the resulting value in this case is implementation-defined(1), which means it's up to the compiler what the result value is, but it must be documented.
(1) C++17 (N4659), [conv.integral] 7.8/3:
If the destination type is signed, the value is unchanged if it can be represented in the destination type;
otherwise, the value is implementation-defined.
Let's start by analysing the result of t - d
.
t
is an unsigned int
while d
is an int
, so to do arithmetic on them, the value of d
is converted to an unsigned int
(C++ rules say unsigned gets preference here). So we get 10u - 16u
, which (assuming 32-bit int
) wraps around to 4294967290u
.
This value is then converted to float
in the first declaration, and to int
in the second one.
Assuming the typical implementation of float
(32-bit single-precision IEEE), its highest representable value is roughly 1e38
, so 4294967290u
is well within that range. There will be rounding errors, but the conversion to float won't overflow.
For int
, the situation's different. 4294967290u
is too big to fit into an int
, so wrap-around happens and we arrive back at the value -6
. Note that such wrap-around is not guaranteed by the standard: the resulting value in this case is implementation-defined(1), which means it's up to the compiler what the result value is, but it must be documented.
(1) C++17 (N4659), [conv.integral] 7.8/3:
If the destination type is signed, the value is unchanged if it can be represented in the destination type;
otherwise, the value is implementation-defined.
edited 40 mins ago
user2357112
143k12147228
143k12147228
answered 9 hours ago
Angew
128k11238334
128k11238334
Just curious, but does in this case implementation-defined means hardware related? Since, most common hardware is two's-complement, you got this behavior, but it would change on a ones-complement CPU even using the same compiler?
â user1810087
9 hours ago
3
@user1810087 It means that the compiler must document what will happen, which means the compiler authors must think about what will happen, and implement it consistently (or at least document it consistently with implementation). It's quite likely their decision will be influenced by the target HW, and so the documentation of this will be platform-specific.
â Angew
9 hours ago
1
It's not behavior which is implementation-defined â only value (see your own footnote). In particular, implementation can't throw an exception, raise a signal etc. due to such conversion.
â Ruslan
7 hours ago
@Ruslan Very good point, thans. Answer edited.
â Angew
6 hours ago
add a comment |Â
Just curious, but does in this case implementation-defined means hardware related? Since, most common hardware is two's-complement, you got this behavior, but it would change on a ones-complement CPU even using the same compiler?
â user1810087
9 hours ago
3
@user1810087 It means that the compiler must document what will happen, which means the compiler authors must think about what will happen, and implement it consistently (or at least document it consistently with implementation). It's quite likely their decision will be influenced by the target HW, and so the documentation of this will be platform-specific.
â Angew
9 hours ago
1
It's not behavior which is implementation-defined â only value (see your own footnote). In particular, implementation can't throw an exception, raise a signal etc. due to such conversion.
â Ruslan
7 hours ago
@Ruslan Very good point, thans. Answer edited.
â Angew
6 hours ago
Just curious, but does in this case implementation-defined means hardware related? Since, most common hardware is two's-complement, you got this behavior, but it would change on a ones-complement CPU even using the same compiler?
â user1810087
9 hours ago
Just curious, but does in this case implementation-defined means hardware related? Since, most common hardware is two's-complement, you got this behavior, but it would change on a ones-complement CPU even using the same compiler?
â user1810087
9 hours ago
3
3
@user1810087 It means that the compiler must document what will happen, which means the compiler authors must think about what will happen, and implement it consistently (or at least document it consistently with implementation). It's quite likely their decision will be influenced by the target HW, and so the documentation of this will be platform-specific.
â Angew
9 hours ago
@user1810087 It means that the compiler must document what will happen, which means the compiler authors must think about what will happen, and implement it consistently (or at least document it consistently with implementation). It's quite likely their decision will be influenced by the target HW, and so the documentation of this will be platform-specific.
â Angew
9 hours ago
1
1
It's not behavior which is implementation-defined â only value (see your own footnote). In particular, implementation can't throw an exception, raise a signal etc. due to such conversion.
â Ruslan
7 hours ago
It's not behavior which is implementation-defined â only value (see your own footnote). In particular, implementation can't throw an exception, raise a signal etc. due to such conversion.
â Ruslan
7 hours ago
@Ruslan Very good point, thans. Answer edited.
â Angew
6 hours ago
@Ruslan Very good point, thans. Answer edited.
â Angew
6 hours ago
add a comment |Â
up vote
12
down vote
First, you have to understand "usual arithmetic conversions" (that link is for C, but the rules are the same in C++). In C++, if you do arithmetic with mixed types (you should avoid that when possible, by the way), there's a set of rules that decides which type the calculation is done in.
In your case, you are subtracting a signed int from an unsigned int. The promotion rules say that the actual calculation is done using unsigned int
.
So your calculation is 10 - 16
in unsigned int arithmetic. Unsigned arithmetic is modulo arithmetic, meaning that it wraps around. So, assuming your typical 32-bit int, the result of this calculation is 2^32 - 6.
This is the same for both lines. Note that the subtraction is completely independent from the assignment; the type on the left side has absolutely no influence on how the calculation happens. It is a common beginner mistake to think that the type on the left side somehow influences the calculation; but float f = 5 / 6
is zero, because the division still uses integer arithmetic.
The difference, then, is what happens during the assignment. The result of the subtraction is implicitly converted to float
in one case, and int
in the other.
The conversion to float tries to find the closest value to the actual one that the type can represent. This will be some very large value; not quite the one the original subtraction yielded though.
The conversion to int says that if the value fits into the range of int, the value will be unchanged. But 2^32 - 6 is far larger than the 2^31 - 1 that a 32-bit int can hold, so you get the other part of the conversion rule, which says that the resulting value is implementation-defined. This is a term in the standard that means "different compilers can do different things, but they have to document what they do".
For all practical purposes, all compilers that you'll likely encounter say that the bit pattern stays the same and is just interpreted as signed. Because of the way 2's complement arithmetic works (the way that almost all computers represent negative numbers), the result is the -6 you would expect from the calculation.
But all this is a very long way of repeating the first point, which is "don't do mixed type arithmetic". Cast the types first, explicitly, to types that you know will do the right thing.
I think you meant2^31-1
for your second value in paragraph 7. Because "2^32 - 6 is far larger than the 2^32 - 1" doesn't, on the face of it, seem an obvious thing to assert. Most people would think that the first was exactly 5 less than the second, not far larger :-)
â Damien_The_Unbeliever
7 hours ago
@Damien_The_Unbeliever Fixed, thanks.
â Sebastian Redl
4 hours ago
add a comment |Â
up vote
12
down vote
First, you have to understand "usual arithmetic conversions" (that link is for C, but the rules are the same in C++). In C++, if you do arithmetic with mixed types (you should avoid that when possible, by the way), there's a set of rules that decides which type the calculation is done in.
In your case, you are subtracting a signed int from an unsigned int. The promotion rules say that the actual calculation is done using unsigned int
.
So your calculation is 10 - 16
in unsigned int arithmetic. Unsigned arithmetic is modulo arithmetic, meaning that it wraps around. So, assuming your typical 32-bit int, the result of this calculation is 2^32 - 6.
This is the same for both lines. Note that the subtraction is completely independent from the assignment; the type on the left side has absolutely no influence on how the calculation happens. It is a common beginner mistake to think that the type on the left side somehow influences the calculation; but float f = 5 / 6
is zero, because the division still uses integer arithmetic.
The difference, then, is what happens during the assignment. The result of the subtraction is implicitly converted to float
in one case, and int
in the other.
The conversion to float tries to find the closest value to the actual one that the type can represent. This will be some very large value; not quite the one the original subtraction yielded though.
The conversion to int says that if the value fits into the range of int, the value will be unchanged. But 2^32 - 6 is far larger than the 2^31 - 1 that a 32-bit int can hold, so you get the other part of the conversion rule, which says that the resulting value is implementation-defined. This is a term in the standard that means "different compilers can do different things, but they have to document what they do".
For all practical purposes, all compilers that you'll likely encounter say that the bit pattern stays the same and is just interpreted as signed. Because of the way 2's complement arithmetic works (the way that almost all computers represent negative numbers), the result is the -6 you would expect from the calculation.
But all this is a very long way of repeating the first point, which is "don't do mixed type arithmetic". Cast the types first, explicitly, to types that you know will do the right thing.
I think you meant2^31-1
for your second value in paragraph 7. Because "2^32 - 6 is far larger than the 2^32 - 1" doesn't, on the face of it, seem an obvious thing to assert. Most people would think that the first was exactly 5 less than the second, not far larger :-)
â Damien_The_Unbeliever
7 hours ago
@Damien_The_Unbeliever Fixed, thanks.
â Sebastian Redl
4 hours ago
add a comment |Â
up vote
12
down vote
up vote
12
down vote
First, you have to understand "usual arithmetic conversions" (that link is for C, but the rules are the same in C++). In C++, if you do arithmetic with mixed types (you should avoid that when possible, by the way), there's a set of rules that decides which type the calculation is done in.
In your case, you are subtracting a signed int from an unsigned int. The promotion rules say that the actual calculation is done using unsigned int
.
So your calculation is 10 - 16
in unsigned int arithmetic. Unsigned arithmetic is modulo arithmetic, meaning that it wraps around. So, assuming your typical 32-bit int, the result of this calculation is 2^32 - 6.
This is the same for both lines. Note that the subtraction is completely independent from the assignment; the type on the left side has absolutely no influence on how the calculation happens. It is a common beginner mistake to think that the type on the left side somehow influences the calculation; but float f = 5 / 6
is zero, because the division still uses integer arithmetic.
The difference, then, is what happens during the assignment. The result of the subtraction is implicitly converted to float
in one case, and int
in the other.
The conversion to float tries to find the closest value to the actual one that the type can represent. This will be some very large value; not quite the one the original subtraction yielded though.
The conversion to int says that if the value fits into the range of int, the value will be unchanged. But 2^32 - 6 is far larger than the 2^31 - 1 that a 32-bit int can hold, so you get the other part of the conversion rule, which says that the resulting value is implementation-defined. This is a term in the standard that means "different compilers can do different things, but they have to document what they do".
For all practical purposes, all compilers that you'll likely encounter say that the bit pattern stays the same and is just interpreted as signed. Because of the way 2's complement arithmetic works (the way that almost all computers represent negative numbers), the result is the -6 you would expect from the calculation.
But all this is a very long way of repeating the first point, which is "don't do mixed type arithmetic". Cast the types first, explicitly, to types that you know will do the right thing.
First, you have to understand "usual arithmetic conversions" (that link is for C, but the rules are the same in C++). In C++, if you do arithmetic with mixed types (you should avoid that when possible, by the way), there's a set of rules that decides which type the calculation is done in.
In your case, you are subtracting a signed int from an unsigned int. The promotion rules say that the actual calculation is done using unsigned int
.
So your calculation is 10 - 16
in unsigned int arithmetic. Unsigned arithmetic is modulo arithmetic, meaning that it wraps around. So, assuming your typical 32-bit int, the result of this calculation is 2^32 - 6.
This is the same for both lines. Note that the subtraction is completely independent from the assignment; the type on the left side has absolutely no influence on how the calculation happens. It is a common beginner mistake to think that the type on the left side somehow influences the calculation; but float f = 5 / 6
is zero, because the division still uses integer arithmetic.
The difference, then, is what happens during the assignment. The result of the subtraction is implicitly converted to float
in one case, and int
in the other.
The conversion to float tries to find the closest value to the actual one that the type can represent. This will be some very large value; not quite the one the original subtraction yielded though.
The conversion to int says that if the value fits into the range of int, the value will be unchanged. But 2^32 - 6 is far larger than the 2^31 - 1 that a 32-bit int can hold, so you get the other part of the conversion rule, which says that the resulting value is implementation-defined. This is a term in the standard that means "different compilers can do different things, but they have to document what they do".
For all practical purposes, all compilers that you'll likely encounter say that the bit pattern stays the same and is just interpreted as signed. Because of the way 2's complement arithmetic works (the way that almost all computers represent negative numbers), the result is the -6 you would expect from the calculation.
But all this is a very long way of repeating the first point, which is "don't do mixed type arithmetic". Cast the types first, explicitly, to types that you know will do the right thing.
edited 4 hours ago
answered 9 hours ago
Sebastian Redl
48.3k474110
48.3k474110
I think you meant2^31-1
for your second value in paragraph 7. Because "2^32 - 6 is far larger than the 2^32 - 1" doesn't, on the face of it, seem an obvious thing to assert. Most people would think that the first was exactly 5 less than the second, not far larger :-)
â Damien_The_Unbeliever
7 hours ago
@Damien_The_Unbeliever Fixed, thanks.
â Sebastian Redl
4 hours ago
add a comment |Â
I think you meant2^31-1
for your second value in paragraph 7. Because "2^32 - 6 is far larger than the 2^32 - 1" doesn't, on the face of it, seem an obvious thing to assert. Most people would think that the first was exactly 5 less than the second, not far larger :-)
â Damien_The_Unbeliever
7 hours ago
@Damien_The_Unbeliever Fixed, thanks.
â Sebastian Redl
4 hours ago
I think you meant
2^31-1
for your second value in paragraph 7. Because "2^32 - 6 is far larger than the 2^32 - 1" doesn't, on the face of it, seem an obvious thing to assert. Most people would think that the first was exactly 5 less than the second, not far larger :-)â Damien_The_Unbeliever
7 hours ago
I think you meant
2^31-1
for your second value in paragraph 7. Because "2^32 - 6 is far larger than the 2^32 - 1" doesn't, on the face of it, seem an obvious thing to assert. Most people would think that the first was exactly 5 less than the second, not far larger :-)â Damien_The_Unbeliever
7 hours ago
@Damien_The_Unbeliever Fixed, thanks.
â Sebastian Redl
4 hours ago
@Damien_The_Unbeliever Fixed, thanks.
â Sebastian Redl
4 hours ago
add a comment |Â
Eugene Kolombet is a new contributor. Be nice, and check out our Code of Conduct.
Eugene Kolombet is a new contributor. Be nice, and check out our Code of Conduct.
Eugene Kolombet is a new contributor. Be nice, and check out our Code of Conduct.
Eugene Kolombet is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52754505%2fwhy-is-the-sign-different-after-subtracting-unsigned-and-signed%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
2
Most compilers have an option to warn you if you're implicitly converting a
signed
value tounsigned
or vice versa. On GCC and Clang, this is-Wconversion
. Your question is a good example of why it's a good idea to compile with that.â Davislor
5 hours ago