C++ 使用不同表达式计算同一整数时结果不一致

C++ 使用不同表达式计算同一整数时结果不一致,c++,integer-arithmetic,unsigned-long-long-int,C++,Integer Arithmetic,Unsigned Long Long Int,同一表达式的算术结果导致不同的结果,这取决于我是在一行中定义一个整数,还是使用几个步骤: int main() { unsigned long long veryBigIntOneLine = ((255*256+255)*256+255)*256+255; unsigned long long veryBigInt = 255; veryBigInt *= 256; veryBigInt += 255; veryBigInt *= 256;

同一表达式的算术结果导致不同的结果,这取决于我是在一行中定义一个整数,还是使用几个步骤:

int main() {

    unsigned long long veryBigIntOneLine = ((255*256+255)*256+255)*256+255;

    unsigned long long veryBigInt = 255;
    veryBigInt *= 256;
    veryBigInt += 255;
    veryBigInt *= 256;
    veryBigInt += 255;
    veryBigInt *= 256;
    veryBigInt += 255;

    unsigned long long veryBigIntParanthesis = (((((255*256)+255)*256)+255)*256)+255;

    unsigned long long fourthInt = 256;
    fourthInt *= 256;
    fourthInt *= 256;
    fourthInt *= 256;
    --fourthInt;

    cout << "veryBigIntOneLine: " << veryBigIntOneLine << endl;
    cout << "veryBigInt: " << veryBigInt << endl;
    cout << "veryBigIntParanthesis: " << veryBigIntParanthesis << endl;
    cout << "fourthInt: " << fourthInt << endl;

    return 0;

}
4294967295是预期的答案(正如谷歌计算器为所有四个表达式给出的那样)

另外,18446744073709551615可能不是计算结果的精确结果,因为我在编译时得到了两个单行表达式的溢出警告(即使我尝试使用类型_int128)。它实际上是2^64-1,这是我的编译器使用的无符号long-long的最大值(veryBigIntOneLine+1给出0)。

初始化代码
((255*256+255)*256+255)*256+255
遭受未定义行为的有符号整数溢出,以及从有符号整数到无符号整数的隐式转换。而分步计算避免了这些问题,因为右侧操作数隐式转换为无符号long-long

只需使用适当的文字即可解决这些问题:

unsigned long long veryBigIntOneLine{ ((255ull*256ull+255ull)*256ull+255ull)*256ull+255ull}; // 4294967295
初始化代码
((255*256+255)*256+255)*256+255
遭受有符号整数溢出(这是一种未定义的行为)以及有符号整数到无符号整数的隐式转换。而分步计算避免了这些问题,因为右侧操作数隐式转换为无符号long-long

只需使用适当的文字即可解决这些问题:

unsigned long long veryBigIntOneLine{ ((255ull*256ull+255ull)*256ull+255ull)*256ull+255ull}; // 4294967295

这是因为您没有使用
无符号long-long
文字。如果希望文字与定义匹配,则需要使用:

255ULL + 256ULL * 255ULL + ...

如果您创建的数字是64位的,
ULL
非常重要。在C语言中,如果没有后缀,数字可能是64位、32位,甚至只有16位(在某些CRAY上是偶数字节,其中64位。这也意味着您的代码只需在CRAY系统中查找即可工作。)

这是因为您没有使用
无符号long
文字。如果希望文字与定义匹配,则需要使用:

255ULL + 256ULL * 255ULL + ...

如果您创建的数字是64位的,
ULL
非常重要。在C语言中,如果没有后缀,数字可能是64位、32位甚至16位(在某些CRAY上是偶数字节,其中64位。这也意味着你的代码只需在CRAY系统中查找即可。)

好的,谢谢,
unsigned long veryBigIntOneLine=(unsigned long long)((255*256+255)*256+255)*256+255工作正常。如果出现提示,大多数编译器都会发出警告。尽管添加
constexpr
会将其更改为一个始终会被诊断的错误:作为旁白,它足以使其中一个内部常量成为
无符号long
,其余部分依赖于隐式提升。@JulienDhondt您只需使用适当的文字后缀,就可以在任何地方使用无符号的long-long。还要注意列表初始化的使用-它禁止缩小转换范围。@重复数据消除器因此基本上,这
unsigned long veryBigIntOneLine=((255ull*256+255)*256+255)*256+255应该有效吗?@JulienDhondt您还可以定义自己的后缀。请参见用户定义的literalOk,谢谢,
unsigned long veryBigIntOneLine=(unsigned long long-long)((255*256+255)*256+255)*256+255工作正常。如果出现提示,大多数编译器都会发出警告。尽管添加
constexpr
会将其更改为一个始终会被诊断的错误:作为旁白,它足以使其中一个内部常量成为
无符号long
,其余部分依赖于隐式提升。@JulienDhondt您只需使用适当的文字后缀,就可以在任何地方使用无符号的long-long。还要注意列表初始化的使用-它禁止缩小转换范围。@重复数据消除器因此基本上,这
unsigned long veryBigIntOneLine=((255ull*256+255)*256+255)*256+255应该有效吗?@JulienDhondt您还可以定义自己的后缀。请参阅用户定义的文字谢谢,我知道的唯一文字说明符是wchar_t[]字符串的“L”。我不知道其他类型的文字表达式是键入的、处理的/计算的,并且只有在定义/赋值时转换后才使用。旁注:
int
不一定是32位的(还有相当多的体系结构具有16位int!)。谢谢,我知道的唯一一个文字说明符是用于wchar_t[]字符串的“L”。我不知道其他类型的文字表达式是键入、处理/计算的,并且只有在定义/赋值转换后才进行的。旁注:
int
不一定是32位的(有相当多的体系结构具有16位int!)。另外,获取
无符号long
最大值的最简单方法是
(-1ULL)
(~0ULL)
。另外,获取
无符号long
最大值的最简单方法是
(-1ULL)
(~0ULL)