0xFFFFFFFFul为(有符号)long:UB,Impl定义还是只是OK?

时间:2016-06-23 07:01:05

标签: c++

此代码是否会在所有理智(例如2-s补码算术)32位机器上打印-1,在LLP64上打印-1(即64位Windows,其中长为32位)和所有64位上的4 gig位Unix OS:es(即在LP64操作系统上):

#include <iostream>

using std::cout;

int main()
{
    long li = 0xfffffffful;

    cout << "size of li: " << sizeof(li) << ", li: " << li << '\n';
}

通常我使用明确定义的相关变量大小,并使用std :: numeric_limits而不是'ul'数字常量。所以我会写类似

的东西
const uint32_t MAX_INTERVAL = std::numeric_limits<uint32_t>::max(); 
const int64_t some_var = MAX_INTERVAL;

1 个答案:

答案 0 :(得分:3)

如果你有至少33位long s没有问题(或者更具体地说,如果4294967295可以表示为long)。行为将被很好地定义为数字可以表示为long

如果你有32位long,那么问题仍然存在。然后行为是实现定义的,这意味着编译器/实现被强制指定行为(最有可能你最终得到-1,但是可能存在奇怪的实现,这会产生另一个结果)。

标准的相关部分是4.7(积分转换):

  
      
  1. 如果目标类型是无符号的,则结果值是与源整数一致的最小无符号整数(模数)   2 ^ n在哪里   ñ   是用于表示无符号类型的位数)。 [   注意:   在一个两个   补码表示,这种转换是概念性的,并且位模式没有变化(如果有的话)   不是截断)。    - 注意   ]

  2.   
  3. 如果目标类型已签名,则如果可以在目标类型中表示该值,则该值不会更改(和   位域宽度);否则,该值是实现定义的。

  4.