C ++标准:奇怪的32位和64位有符号/无符号算术除法行为

问题描述 投票:2回答:2

我遇到了我的代码的错误行为。研究它使我得到一个简短的示例,该示例显示了问题:

//g++  5.4.0

#include <iostream>
#include <vector>

int main()
{
    std::vector<short> v(20);

    auto D = &v[5] - &v[10];   
    auto C = D / sizeof(short);

    std::cout << "C = " << C;

}

这个例子很常见。它将显示什么结果?

C = 9223372036854775805

在这里测试:https://rextester.com/l/cpp_online_compiler_gcc还针对Clang C ++VS C ++C进行了测试。结果相同。

与同事讨论时,我指向文档https://en.cppreference.com/w/cpp/language/operator_arithmetic#Conversions

它告诉:

  • [如果两个操作数都带符号或都为无符号,则转换等级较小的操作数将转换为整数转换等级较大的操作数
  • 否则,如果无符号操作数的转换等级大于或等于有符号操作数的转换等级,则将有符号操作数转换为无符号操作数的类型。
  • 否则,如果有符号操作数的类型可以表示无符号操作数的所有值,则无符号操作数将转换为有符号操作数的类型

似乎second规则在这里起作用。但这是not正确。

为了确认second规则,我已经测试过这样的示例:

//g++  5.4.0
#include <iostream>

int main()
{
            typedef uint32_t u_t; // uint64_t, uint32_t, uint16_t uint8_t
            typedef int32_t i_t;  // int64_t, int32_t, int16_t int8_t

            const u_t B = 2;
            const i_t X = -1;

            const i_t A1 = X * B;
    std::cout << "A1 = X * B = " << A1 << "\n";

            const i_t C = A1 / B;  // signed / unsigned division
    std::cout << "A1 / B = " << C << "\n";
}

具有u_ti_t的不同<< rank >>组合,发现它对于任何组合均正常工作,对于3264位,EXCEPTint64_t / uint64_tint32_t / uint32_t)。因此second规则DOES NOT适用于168位。注意:

乘法

操作在所有情况下均正常工作。因此,这只是division问题。

SECOND

规则听起来像是错误的:
有符号操作数被转换为无符号操作数的类型

The

signed无法转换为unsigned-它是!!错误!!表示NEGATIVE值!但是相反的转换是正确的-无符号操作数被转换为有符号操作数的类型看这一点,我可以注意到,这是C ++标准算术运算中可能存在的错误。代替:

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.

应该是:

Otherwise, if the signed operand's conversion rank is greater or equal to the conversion rank of the unsigned operand, the unsigned operand is converted to the signed operand's type.

我认为,如果满足

signed

unsigned multiplication / division,则将unsigned操作数转换为signed,然后投放到正确的等级。至少跟随x86 Assembler[,请告诉我这是哪里错误。我希望这篇文章中的第一个测试对于代替

auto

类型涉及的任何类型都适用,但是现在[可能并且C ++ Standard告诉它是正确的行为。
很抱歉提出了一个奇怪的问题,但我对这个问题感到困惑。我使用C / C ++编写代码已有30年了,但这是我无法明确解释的第一个问题-是错误还是预期的行为。我遇到了我的代码的错误行为。研究它会使我举一个简短的例子来说明问题:// g ++ 5.4.0 #include

#include

int main(){std :: ...

c++ standards division integer-arithmetic
2个回答
1
投票

-1
投票
所以size_t中的-5 / (size_t) 2将是

[D / sizeof(short)(而不是(size_t) -5 / (size_t) 2]] >>

所以-5的无符号长整数与负数方法/技术有关,它主要是2的补数,然后除以其自身类型的2]]

© www.soinside.com 2019 - 2024. All rights reserved.