Search code examples
c++arraysinitializationintlist-initialization

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;
}

The above code will get the following error:

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

But the following code works perfectly:

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

So my question is: Why can't I use '0x80000000' to initialize an array of int?


Solution

  • 0x80000000 can't fit int here, so it's an 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 (since 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

    And about the behavior of the implicit conversion, i.e. integral conversions in the assignment:

    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.

    The behavior of out of range conversion is implementation-defined, e.g. it may wrap around according to the rules of the representation (typically 2's complement).