On Tue, 7 Jan 2020 at 06:46, Владимир Прокофьев via Std-Proposals <std-proposals@lists.isocpp.org> wrote:

I have found a mistake in the C++ Standard, https://en.cppreference.com/w/cpp/language/operator_arithmetic#Conversion : in the rule:

Otherwise, if the unsigned operand's conversion rank is greater or equal to the conversion rank of the signed operand, the signed operand is converted to the unsigned operand's type.The NEGATIVE signed value CANNOT be converted to unsigned for any types. But opposite conversion from unsigned to signed is valid with appropriate rank.

Surely this depends on the value of the operands. For example, the expression "0x80000000U/2" comes out just fine. Would that still be the case if signed -- not unsigned -- was chosen on the rank tie-breaker?

To prove, please see wrong results here https://rextester.com/CKKDX46498

(Minor point: do your row and column headings have the wrong signedness?)

Note, that the error is observed for VS, CLang and GCC C++ compilers.

As you can see the error is observer indivisionoperation tounsigned32and64bits.

Thedivisionoperation toSIGNEDtypes is VALID (seefirsttable in the example).

Alsomultiplicationof signed and unsigned values is VALID.

You mean multiplication is mathematically correct *with* the 'fix', right? I think you can make the same claim with most of the binary operators. Division is perhaps among the more surprising operators in this respect but I believe this design choice is fairly consistent. For example "-1<1U" evaluates to false.

The example above shows that the C++ compiler shows

unreliablebehavior which leads to produce wrong values as a result of division.

The correct ruleshallbe:

Otherwise, unsigned operand is converted to signedtype of same or higherconversion rankof unsignedoperand's type and then the operand with lesserconversion rankis converted to the operand with the greater conversion rank

I agree that the choice that was made was unfortunate in the post-16-bit era. But remember that when `int` was 16-bit, the alternative would have meant that "40000<30000" was true. Also pretty surprising.

Ultimately, there's no way you can guarantee the correct result with mixed-signedness operands. So the rule we really need to enforce (in tooling) is "ES.100: Don't mix signed and unsigned arithmetic".

John

--С уважением.

Владимир.

Std-Proposals mailing list

Std-Proposals@lists.isocpp.org

https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals