C++ 转换为整数->;由标准定义的无符号long long

C++ 转换为整数->;由标准定义的无符号long long,c++,type-conversion,standards,C++,Type Conversion,Standards,我找不到在标准中如何将int值转换为无符号long的确切规范。指定了各种类似的转换,例如int->unsigned、unsigned->int(如果为负,则为UB)、unsigned long->int等 例如,GCC,-1被转换为0xffffffffffff,而不是0x00000000ffffffff。我可以依赖此行为吗?是的,它定义为: C++11§4.7[conv.integral]/2规定: 如果目标类型是无符号的,则结果值是与源整数全等的最小无符号整数(模2n,其中n是用于表示无符号类

我找不到在标准中如何将
int
值转换为
无符号long
的确切规范。指定了各种类似的转换,例如int->unsigned、unsigned->int(如果为负,则为UB)、unsigned long->int等

例如,GCC,
-1
被转换为
0xffffffffffff
,而不是
0x00000000ffffffff
。我可以依赖此行为吗?

是的,它定义为:

C++11§4.7[conv.integral]/2规定:

如果目标类型是无符号的,则结果值是与源整数全等的最小无符号整数(模2n,其中n是用于表示无符号类型的位数)


与-1全等的最小无符号整数(模2
sizeof(unsigned long long)
)是
unsigned long
可能的最大值。

是的,这是一个很好的定义,它基本上是将
max unsigned long long+1
添加到
-1
,而
max unsigned long long
。这在
4.7
积分转换一节中有介绍,该节说明:

如果目标类型是无符号的,则结果值是与源整数全等的最小无符号整数(模2n,其中n是用于表示无符号类型的位数)。[注:在2的补码表示中,这种转换是概念性的,位模式没有变化(如果没有截断)。-结束注]

它的功能与C99相同,但更容易理解,参见第6.3.1.3节有符号和无符号整数:

否则,如果新类型是无符号的,则通过重复添加或 比新类型中可以表示的最大值多减去一个 直到值在新类型的范围内。49)

其中脚注
49
表示:

这些规则描述的是基于数学值的算术运算,而不是给定类型表达式的值


无符号整数有保证的模运算。因此,任何
int
值v被转换为
无符号长
值u,使得u=K*2n+v,其中K为0或1,其中n为
无符号长
的值表示位数。换句话说,如果v是负数,只需加2n


2的幂遵循C++标准的要求,即用纯二进制系统表示整数。对于n个值表示位,可能值的数量为2n。对浮点类型没有这样的要求(可以使用

std::numeric\u limits
检查浮点值表示的基数)



还要注意的是,为了迎合一些现在已经过时的平台,以及一个以自己的方式处理事情的流行编译器,当无符号值不能直接表示为有符号值时,该标准将相反的转换保留为未定义的行为。在实践中,在现代系统中,所有编译器都可以被告知,反向转换与转换为无符号类型正好相反,例如VisualC++在默认情况下这样做。但是,值得记住的是,没有正式的支持,因此可移植代码会导致一点效率低下(现在现代计算机不需要了)。

这看起来像符号扩展:所以可能是的。有两种可能性:1)转换为
,然后转换为
无符号长
;2) 转换为
无符号
和转换为
无符号长
。标准字母的优先顺序并不明显。@user12:这样做的方式既不是你的两种可能性,而是从
int
无符号long
的方向转换。如果后者更大(通常是这样),则在具有带符号整数值的2的补码表示的普通机器上,执行符号扩展。符号扩展包括简单地复制最高有效位(符号位)以填充左侧。
k
理论上可以是0或1以外的值,如果
无符号
值较小,但是
long
long
不会小于
int
。顺便说一句,我发誓最近这里发生了变化/澄清了一些事情,wrt
int
类型大于
int
。@Yakk:是的,对于涉及的其他类型,可以有其他(积分)K值。再次澄清,我不认为是我。我记得几年前,有人问起内置类型的范围,我把它们提到了C标准。这引起了孩子的愤怒,他拒绝相信C标准中的任何东西都可以应用于C++。或者他/他们想让我做一些腿部工作,找到并引用相关段落。他或他们也拒绝相信2的幂与数字范围有任何关系。这有点令人不快。我的意思是,我认为C/C++wrt整数类型中有一个比
int
long
大的bug,最近被修复了(比如C++11或类似的东西)@Yakk:不,不完全是一个bug,但C++03不支持
long
,因为C++03只是对C++98的技术修正,它出现在C99之前(其中引入了
long-long
)。C++11基于C99,因此确实有
long-long
。C++11也有C99的
,但不幸的是,在匆忙实现C++11标准化的过程中,受支持的C头列表有三个不同的计数:-)(现在已经修复,但我不认为这是您所指的)。哦,带负参数的除法和余数的结果现在定义得很好,四舍五入到0。