Skip to main content
GameDev.net gamedev.net
🔒 Locked

wierd warning :O help

Started by peter_b Feb 16, 2007 at 8:26 AM 9 replies 1.8k views
Original Post
peter_b
peter_b
http://img153.imageshack.us/my.php?image=retardedwarninggq3.jpg check that out.. This code: unsigned short s123; s123+=s123; generates this warning: warning C4244: '+=' : conversion from 'int' to 'unsigned short', possible loss of data How can this be? Why does the compiler think it is an int? Compiler settings are Win32 Debug
Shields up! Rrrrred alert!
Evil Steve
Evil Steve
s123+=s123;
Is effectively the same as:
s123 = s123 + s123;

What if s123 has the value 0xf000?
peter_b
peter_b
isn't the same true for all datatypes? i dont see int's doing that =o
Shields up! Rrrrred alert!
swiftcoder
swiftcoder
No matter how large a value I give to an integral type, I can't generate even a warning for += under GCC 4. It seems a very odd behaviour anyway, shouldn't an unsigned integral value wrap around when it exceeds its maximum range?
Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]
Mastaba
Mastaba
When you use warning level 4, the compiler emits semi-paranoid warnings.
Use s123=s123+s123 and the warning goes away.
Bregma
Bregma
Quote:
Original post by swiftcoder... shouldn't an unsigned integral value wrap around when it exceeds its maximum range?


Yes, that's required behaviour according to the C and C++ standards.

At no time should there be an integral promotion in the original poster's expression. That is clearly a bug in the compiler implementation. The compiler vendor should hang its head in shame.

--smw
Stephen M. Webb
Professional Free Software Developer
mcfly
mcfly
Quote:
Original post by Bregma
At no time should there be an integral promotion in the original poster's expression.

Yes there should. They will be promoted to either int or unsigned int depending on the implementation. Since INT_MAX > USHRT_MAX in this case, the output is the following:

s123 = (unsigned short) ((int) s123 + (int) s123);
Zahlman
Zahlman
Quote:
Original post by mcfly
Quote:
Original post by Bregma
At no time should there be an integral promotion in the original poster's expression.

Yes there should. They will be promoted to either int or unsigned int depending on the implementation. Since INT_MAX > USHRT_MAX in this case, the output is the following:

s123 = (unsigned short) ((int) s123 + (int) s123);


Sorry, that's nonsense. This isn't Java; adding short + short doesn't require a promotion to int. I think I would trust Bregma on this one. You do know what he does for a living, right? :)

Regardless, I would if anything expect the binary version to generate a warning, instead of the immediate one. After all, warnings of this sort are intended to let you reconsider the type of the destination variable, instead of just blindly casting everything. When you're doing +=, changing the type of the "destination" is considerably less helpful ;)

I actually thought about this for a numeric library I wanted to do. The idea was that you'd have unsigned integral types (among others) templated on a bit size, and operator+(integer, integer) would return an integer - i.e. the smallest type that necessarily wouldn't overflow. But integer::operator+= doesn't have this luxury, as you can't change the underlying type, and you need to be able to accumulate values in a loop with a statically typed variable.
mcfly
mcfly
Quote:
Original post by Zahlman
Sorry, that's nonsense. This isn't Java; adding short + short doesn't require a promotion to int.
Nonsense my ass. Look up section 6.3.1.1 in the standard and see for yourself.

Quote:
If an int can represent all values of the original type, the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions.48) All other types are unchanged by the integer promotions.

48) The integer promotions are applied only: as part of the usual arithmetic conversions, to certain argument expressions, to the operands of the unary +, -, and ~ operators, and to both operands of the shift operators, as specified by their respective subclauses.
CTar
CTar
Quote:
Original post by mcfly
Quote:
Original post by Zahlman
Sorry, that's nonsense. This isn't Java; adding short + short doesn't require a promotion to int.
Nonsense my ass. Look up section 6.3.1.1 in the standard and see for yourself.

Quote:
If an int can represent all values of the original type, the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions.48) All other types are unchanged by the integer promotions.

48) The integer promotions are applied only: as part of the usual arithmetic conversions, to certain argument expressions, to the operands of the unary +, -, and ~ operators, and to both operands of the shift operators, as specified by their respective subclauses.


What standard is that? In the 2003 C++ standard (ISO/IEC 14882:2003) chapter 6 is "Statements" and section 6.3 is "Compound statement or block", there exists no 6.3.1. I tried searched for your quote, but I couldn't find anything anywhere in the C++ standard. I even looked up footnote 48 and it explains the reason for doing something. Section 4.5 however deals with integral promotions and the interesting part of it is:
Quote:
An rvalue of type char, signed char, unsigned char, short int, or unsigned short int can be converted to an rvalue of type int if int can represent all the values of the source type; otherwise, the source rvalue can be converted to an rvalue of type unsigned int.
Bregma
Bregma
Quote:
Original post by CTar
What standard is that?

It's the C standard (which is included in the C++ standard by reference).

I see nothing in the OP's expression that requires a promotion to a parger integral type. I don't see any of the enumerated operators, it's not an argument expression, and I fail to see any of the usual arithmetic conversions.

Note that the result of adding two unsigned shorts will always fit in an unsigned short.

I don't really think the issue of integral promotion is relevant, since under two's-complement arithmetic the end result would be the same whether you simply wrap around the result of an unsigned addition or if you promote to a larger signed integral size and truncate the result. Arithmetically, the result is the same so the compiler writer is free to implement the expression that way.

What's wrong is issuing a diagnostic about loss of precision: the standard mandates that when you add two unsigned integral values, the result will wrap around. There is no loss of precision. There is no error, no undefined- or implementation-defined behaviour that might cause problems if you rely on it. There is absolutely no reason for a diagnostic to be issued for the OP's code unless there is a (minor, mostly harmless) bug in the compiler. I should be able to add two unsigned short ints and assign the result to an unsigned short int without any diagnostic whatever.

Now, if the problem expression was something like
s123 += 10;
then I could see why the diagnostic should be issued since the rvalue of the += expression would be promoted to an int and the compiler wouldn't know any better.

--smw
Stephen M. Webb
Professional Free Software Developer

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.