为啥我不能使用'0x80000000'来初始化一个int数组?
Posted
技术标签:
【中文标题】为啥我不能使用\'0x80000000\'来初始化一个int数组?【英文标题】:Why can't I use '0x80000000' to initialize an array of int?为什么我不能使用'0x80000000'来初始化一个int数组? 【发布时间】:2016-09-04 12:22:10 【问题描述】:#include<iostream>
int main()
int arr[1] = 0x80000000;
std::cout<<arr[0]<<"\n";
return 0;
上面的代码会报如下错误:
错误:将“2147483648u”从“unsigned int”缩小到 '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
的数组?
【问题讨论】:
你可以,只是不是 32-but 类型(int
似乎在你的机器上)。
[1]
是一个红鲱鱼,你会得到与普通 int
相同的行为
【参考方案1】:
0x80000000
在这里不能容纳 int
,所以它是 integer literal 类型为 unsigned int
。对于初始化,需要隐式转换,但除了赋值之外,隐式转换是有限的,即在list initialization(C++11 起)中禁止缩小转换:
list-initialization 通过禁止以下内容来限制允许的隐式转换:
... 从整数或无作用域枚举类型转换为不能表示原始所有值的整数类型,除非源是一个常量表达式,其值可以完全存储在目标类型中
关于隐式转换的行为,即赋值中的integral conversions:
如果目标类型是有符号的,如果源整数可以在目标类型中表示,则值不会改变。否则结果是实现定义的。
超出范围转换的行为是实现定义的,例如它可以根据表示的规则(通常是 2 的补码)进行环绕。
【讨论】:
回复。最后一段:这称为超出范围的转换,而不是溢出(当算术运算产生超出范围的结果时会发生这种情况)【参考方案2】:它不能“完美地工作”。当您使用静默允许截断的构造时,它可能编译,但这并不意味着不会发生截断。您仍然会得到错误的结果,因为您的值不适合 signed int
,在这种情况下编译器无法帮助您发现错误。
记住; “编译”!=“工作”。
【讨论】:
【参考方案3】:因为这里arr[0] = 0x80000000;
编译器执行强制转换(这里我们说的是int=32 位),它是实现定义的(取决于编译器)。您也可能会在某些编译器上收到警告。
但编译器在初始化时无法执行强制转换,因为它直接将数组映射到内存。
【讨论】:
只是吹毛求疵。编译器执行转换,有些是隐式的,有些是显式的。程序员通过 casting 指定这样的显式转换。 您没有提到自 C++11 以来此 conversion (未强制转换)不会发生的重要一点,代码格式不正确。然而,它与“将数组直接映射到内存”(无论这应该是什么意思)无关。此代码在 C++03 中是合法的(如您所解释的具有实现定义的行为)。 C++11 中的更改旨在帮助程序员避免编写错误,而不是出于任何技术限制。以上是关于为啥我不能使用'0x80000000'来初始化一个int数组?的主要内容,如果未能解决你的问题,请参考以下文章
java.io.IOException: setDataSource failed.: status=0x80000000问题的解决
强制在Windows上以32位进程加载DLL以上2GB(0x80000000)
在 android 上播放本地 m3u8 文件,显示 setDataSourceFD 失败。:状态 = 0x80000000
MediaPlayer setDataSource 失败,状态 = 0x80000000 为 2.3.4 上的文件路径设置的铃声