uint64_t中的唯一值是否也将在int64_t中唯一

时间:2019-05-15 20:35:25

标签: c++ c++11 language-lawyer

给定一个唯一(std::uint64_t类型)整数的向量,如果我将(std::uint64_t类型)的向量强制转换为(std::int64_t类型)的向量,则可以保证是独特吗?

像这样铸造

std::vector<std::uint64_t> unsignedVec;
std::vector<std::int64_t> signedVec( unsignedVec.begin(), unsignedVec.end() );

3 个答案:

答案 0 :(得分:8)

  

是否可以保证唯一?

形式上是实现定义的,但是在任何明智的平台上,它应该是唯一的。

(特别是如果提供int64_t has to be 2的补码。)

自C ++ 20起,它具有唯一性。


  

https://en.cppreference.com/w/cpp/language/implicit_conversion#Numeric_conversions

     

如果目标类型是带符号的,则如果源整数可以用目标类型表示,则值不会更改。 [否则结果是实现定义的(直到C ++ 20)] [目标类型的唯一值等于源值的模2 n    其中,n是用于表示目标类型的位数。 (自C ++ 20起)。

答案 1 :(得分:3)

使用{p>结束于signedVec的值

std::vector<std::int64_t> signedVec( unsignedVec.begin(), unsignedVec.end() );
如果unsignedVec中的对应值大于std::int64_t可以表示的值,则

将在C ++ 11中实现定义。否则,值将是相同的[conv.integral]/3

  

如果目标类型是带符号的,则该值可以用目标类型(和位域宽度)表示;否则,该值是实现定义的。

注意:C ++ 11通过[headers]/4从C99继承了std::int64_t的定义。 int64_t在C99 [7.18.1.1] / 1中被指定为(强调我;感谢@Bob__指出了这一点):

  

typedef名称intN_t指定一个带符号的整数类型,其宽度为 N 没有填充位,并且用两个补码表示

和[7.18.1.1] / 3

  

这些类型是可选的。但是,如果实现提供的整数类型的宽度为8位,16位,32位或64位,没有填充位,并且(对于有符号类型)具有二进制补码表示,则它应定义相应的typedef名称。

因此,尽管在技术上仍是实现定义的,但是如果代码编译,则值将不太可能是唯一的(只有在定义std::int64_t时,值才是唯一的,因为这是可选的)。由于int64_t被指定为具有二进制补码表示形式,并且仅在实现可以支持的情况下定义该定义,因此转换以除预期方式之外的任何方式运行都将非常令人惊讶。我从未听说过编译器无法正常运行。此外,如answer by @HolyBlackCat中指出的那样,从C ++ 20 [conv.integral]/3开始,将需要所需的行为…

答案 2 :(得分:1)

使用给定的代码,存在两种可能的情况:

  • 原始向量unsignedVec的所有元素均小于或等于std::numeric_limits<int64_t>::max()。在这种情况下,目标向量元素将与原始向量元素相同,并且所有属性都将保留。
  • 原始向量中的元素大于std::numeric_limits<int64_t>::max()。在这种情况下,程序行为未在标准中定义,应由实施来决定,一切都会发生。