为什么我不能使用 '0x80000000' 来初始化一个 int 数组?

Why can't I use '0x80000000' to initialize an array of int?

#include<iostream>
int main()
{
    int arr[1] = {0x80000000};
    std::cout<<arr[0]<<"\n";
    return 0;
}

以上代码会出现如下错误:

error: narrowing conversion of ‘2147483648u’ from ‘unsigned int’ to ‘int’ inside { } [-Wnarrowing] int arr[1] = {0x80000000};

但下面的代码可以完美运行:

#include<iostream>    
int main()
{
    int arr[1];
    arr[0] = 0x80000000;
    std::cout<<arr[0]<<"\n";
    return 0;
}

所以我的问题是:为什么我不能使用'0x80000000'来初始化int的数组?

因为这里 arr[0] = 0x80000000; 编译器执行强制转换(我们在这里谈论 int=32 位),这是实现定义的(取决于编译器)。您也可能会在某些编译器上收到警告。

但是编译器无法在初始化时进行强制转换,因为它直接将数组映射到内存。

0x80000000 不能放在这里 int,所以它是一个 integer literal with type unsigned int. For initialization, implicit conversion is needed, but other than assignment, implicit conversions are limited, i.e. narrowing conversions are prohibited in list initialization (C++11 起):

list-initialization limits the allowed implicit conversions by prohibiting the following:

  • ...
  • conversion from integer or unscoped enumeration type to integer type that cannot represent all values of the original, except where source is a constant expression whose value can be stored exactly in the target type

关于隐式转换的行为,即赋值中的 integral conversions

If the destination type is signed, the value does not change if the source integer can be represented in the destination type. Otherwise the result is implementation-defined.

超出范围的转换行为是实现定义的,例如它可能会根据表示规则环绕(通常是 2 的补码)。

它没有"work perfectly"。当您使用静默允许截断的构造时,它可能 编译 ,但这并不意味着不会发生截断。您仍然会得到错误的结果,因为您的值不适合 signed int,在这种情况下,编译器不会帮助您发现错误。

记住; "compiles" != "works".