C++ <;功能性>;:加<;长期>;()在整数上给出意外的结果

C++ <;功能性>;:加<;长期>;()在整数上给出意外的结果,c++,g++,C++,G++,我不明白为什么在这两种情况下我得不到相同的结果: #include <iostream> #include <vector> #include <numeric> // for accumulate #include <functional> // for plus() using namespace std; int main() { long long i = (long long) 0xFFFFFFFF + 2; cout

我不明白为什么在这两种情况下我得不到相同的结果:

#include <iostream>
#include <vector>
#include <numeric> // for accumulate
#include <functional> // for plus()
using namespace std;

int main() {
    long long i = (long long)  0xFFFFFFFF + 2;
    cout << i << endl;

    vector<int> v;
    v.push_back(0xFFFFFFFF);
    v.push_back(2);

    long long r = accumulate(v.begin(), v.end(), 0, plus<long long>());
    cout << r << endl;

    return 0;
}
#包括
#包括
#包括//用于累计
#include//for plus()
使用名称空间std;
int main(){
long long i=(long long)0xFFFFFFFF+2;

这里有两个问题:

  • 数字0xFFFFFF不适合
    int
    (假设为32位
    int
    s),因此在大多数实现中存储在向量中的值实际上是-1。使用
    vector
    vector
    应该可以解决这个问题

  • accumulate
    返回的类型是从第三个参数推断出来的类型。由于您传入了
    0
    ,因此它将是
    int
    。您应该传入
    0LL
    ,使其返回
    long

  • #include <iostream>
    #include <vector>
    #include <numeric> // for accumulate
    #include <functional> // for plus()
    using namespace std;
    
    int main() {
        long long i = (long long)  0xFFFFFFFF + 2;
        cout << i << endl;
    
        vector<long long> v;
        v.push_back(0xFFFFFFFF);
        v.push_back(2);
    
        long long r = accumulate(v.begin(), v.end(), 0LL, plus<long long>());
        cout << r << endl;
    
        return 0;
    }
    
    此程序和两个修复程序将返回正确的结果:

    #include <iostream>
    #include <vector>
    #include <numeric> // for accumulate
    #include <functional> // for plus()
    using namespace std;
    
    int main() {
        long long i = (long long)  0xFFFFFFFF + 2;
        cout << i << endl;
    
        vector<long long> v; //or vector<unsigned int>
        v.push_back(0xFFFFFFFF);
        v.push_back(2);
    
        long long r = accumulate(v.begin(), v.end(), 0LL, plus<long long>());
        cout << r << endl;
    
        return 0;
    }
    
    #包括
    #包括
    #包括//用于累计
    #include//for plus()
    使用名称空间std;
    int main(){
    long long i=(long long)0xFFFFFFFF+2;
    
    无法,因为向量包含类型
    int
    ,并且0xFFFFFF不适合它。请尝试将其更改为
    long

    #include <iostream>
    #include <vector>
    #include <numeric> // for accumulate
    #include <functional> // for plus()
    using namespace std;
    
    int main() {
        long long i = (long long)  0xFFFFFFFF + 2;
        cout << i << endl;
    
        vector<long long> v;
        v.push_back(0xFFFFFFFF);
        v.push_back(2);
    
        long long r = accumulate(v.begin(), v.end(), 0LL, plus<long long>());
        cout << r << endl;
    
        return 0;
    }
    
    #包括
    #包括
    #包括//用于累计
    #include//for plus()
    使用名称空间std;
    int main(){
    long long i=(long long)0xFFFFFFFF+2;
    
    cout您的
    vector
    存储类型
    int
    ,这可能是一种32位类型。从4.7/3中,我们了解到:

    如果目标类型是有符号的,则该值将保持不变(如果可以) 在目标类型(和位字段宽度)中表示;否则, 该值由实现定义

    换句话说,您的值
    0xFFFFFFFF
    不能在目标签名类型中表示,因此结果是实现定义的。在这种情况下,它很可能采用明显的twos comp结果,并在向量中存储
    -1
    。然后当您进行
    累加时,它会添加
    -1
    (因为它不会更改存储的-1)和
    2
    ,从而打印
    1


    很可能您希望在向量中存储
    long
    (因为您对大于32位的值求和),如其他答案所述,您还需要通过
    0LL
    来累加,以迫使它推断正确的返回类型。

    您得到了哪两种不同的结果,您期望得到什么?现在我明白了,应该采用0x7FFFFFFFFF…抱歉,愚蠢的问题。这里稍微有点错误,但存储的值不必是
    -1
    ,这是实现是的,我假设了32位2的补码表示。这是正确的,但我希望对整数求和,而不会导致换行或意外行为。