xml*_*lmx 3 c++ standards numeric compile-time-constant unsigned-integer
#include <iostream>
#include <cstdint>
using namespace std;
static_assert(-1 == numeric_limits<uint64_t>::max()); // ok
static_assert(-1 == numeric_limits<uint32_t>::max()); // ok
static_assert(-1 == numeric_limits<uint16_t>::max()); // error
int main()
{
cout << numeric_limits<uint16_t>::max() << endl;
cout << uint16_t(-1) << endl;
}
Run Code Online (Sandbox Code Playgroud)
输出:
65535
65535
Run Code Online (Sandbox Code Playgroud)
为什么 numeric_limits<uint16_t>::max() 不等于-1?
更新:
根据cppref:
类似地,USHRT_MAX 可能不是无符号类型:它的类型可能是 int。
该uint16_t值经过整数提升,而对于(您的特定平台;见下文)uint32_t和uint64_t情况下的-1 值(本身不是整数文字,而是应用于整数文字的一元减号运算符1),通过整数转换得到结果值由于此转换的源值和目标值之间的整数全等,它等于uint32_t和uint64_t类型的最大相应值。
static_assert(-1 == std::numeric_limits<std::uint64_t>::max());
// ^^
// | Integer conversion:
// | Destination type: uint64_t
// | Resulting value: std::numeric_limits<std::uint64_t>::max()
static_assert(-1 == std::numeric_limits<std::uint32_t>::max());
// ^^
// | Integer conversion:
// | Destination type: uint32_t
// | Resulting value: std::numeric_limits<std::uint32_t>::max()
static_assert(-1 == std::numeric_limits<std::uint16_t>::max());
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// | Integer promotion:
// | Destination type: int
// | Resulting value: std::numeric_limits<std::uint16_t>::max()
Run Code Online (Sandbox Code Playgroud)
来自[expr.eq]/1和[expr.eq]/6 [强调我的]:
[表达式]/1
的
==(等于)和!=(不等于)运算符组左到右。操作数应具有算术、枚举、指针或指向成员类型或类型的指针std?::?nullptr_t。运算符==and!=都产生trueorfalse,即类型的结果bool。在下面的每种情况下,在应用指定的转换后,操作数应具有相同的类型。[表达式]/6
如果两个操作数都是算术**或枚举类型,则对两个操作数执行通常的算术转换;
true如果指定的关系是true并且false如果是 ,则每个运算符都应屈服false。
从[conv.integral]/1和[conv.integral]/2:
[转换积分]/1
整数类型的纯右值可以转换为另一种整数类型的纯右值。无作用域枚举类型的纯右值可以转换为整数类型的纯右值。
[conv.integral]/2
如果目标类型是无符号的,则结果值是与源整数一致的最小无符号整数(取模
2n,其中n是用于表示无符号类型的位数)。[?注:在二进制补码表示中,这种转换是概念性的,位模式没有变化(如果没有截断)。?—?尾注?]
仅此一项就应该为所有三个示例产生相同的行为。但是,这种uint16_t情况的不同之处在于[conv.integral]/5适用:
[转换积分]/5
允许作为积分促销的转换不包括在积分转换集中。
[转化率排名]/1
每个整数类型都有一个整数转换等级,定义如下:
[...]
(1.3) 的等级
long long int应大于 的等级long int,应大于的等级int,应大于 的等级short int,应大于 的等级signed char。(1.4) 任何无符号整数类型的等级应等于相应有符号整数类型的等级。
uint16_t(same rank or belowshort int )的整数转换等级低于的整数转换等级int,这意味着[conv.prom]/1适用于uint16_t[强调我的]:
[转化率]/1
bool,char16_t,以外的整数类型的纯右值char32_t,或其wchar_t整数转换等级小于 的等级,intint如果int可以表示源类型的所有值,则可以转换为类型的纯右值;否则,可以将源纯右值转换为 类型的纯右值unsigned int。
然而,虽然我们能够作出的论据uint16_t之上,由于对最大值下限要求的的unsigned short int-guaranteeing是uint16_t始终具有较低的整数转换等级比int-我们无法对这一事实相反的说法uint32_t会不会有下整数转换等级比int,因为 ISO C++ 标准对基本整数类型的最大值要求没有上限。
来自[basic.fundamental]/2和[basic.fundamental]/3 [摘录,重点是我的]:
[基础.基础]/2
有五种标准的有符号整数类型:“
signed char”、“short int”、“int”、“long int”和“long long int”。在此列表中,每种类型至少提供与列表中它之前的类型一样多的存储空间。[...] Plainints具有执行环境架构建议的自然大小;提供其他有符号整数类型以满足特殊需要。[基础.基础]/3
对于每一种标准的有符号整数类型,都存在一个对应的(但不同的)标准无符号整数类型:“
unsigned char”、“unsigned short int”、“unsigned int”、“unsigned long int”和“unsigned long long int”,它们各自占用相同的存储量,并具有与相应的有符号整数类型相同的对齐要求;[...]有符号和无符号整数类型应满足 C 标准第 5.2.4.2.1 节中给出的约束。
并且,来自C11 标准草案[摘录,强调我的]:
5.2.4.2.1 整数类型的大小
<limits.h>[...] 它们的实现定义的值在数量级(绝对值)上应等于或大于所示值,并具有相同的符号。
[...]
类型对象的最大值
short int:SHRT_MAX +32767类型对象的最大值
int:INT_MAX +32767[...]
请注意,这些最大值描述了相应基本整数类型应能够存储的最大值的下限,而对这些最大值的上限没有要求。此外,从上面的 [basic.fundamental]/2 引用中回想一下,每个后续的基本(有符号)整数类型只需要提供至少与处理它的类型(在列表中)一样多的存储空间。
这意味着,从理论上讲,一个平台可以实现short int和int32位宽和64毕特宽的整数,分别的,这意味着,在该平台上,uint32_t将具有相同的整数转换秩为(unsigned)short int,这将意味着一个较低的比转换秩int,在这种情况下[conv.prom]/1也适用于该特定平台上的uint32_t示例。
| 归档时间: |
|
| 查看次数: |
4144 次 |
| 最近记录: |