对于__int128 @min负值,整数溢出UDL(用户定义的文字)

时间:2014-08-05 16:02:07

标签: c++ c++11 integer-overflow user-defined-literals int128

为了清楚和简单起见,我将缩短以下数字如下:

  • −170,141,183,460,469,231,731,687,303,715,884,105,728-170…728
  • 170,141,183,460,469,231,731,687,303,715,884,105,727170…727

这些数字代表128位有符号整数的最小值和最大值(gcc中的__int128)。

我为此数据类型实现了用户定义的文字(原始文字),因为gcc没有提供定义此类型常量的方法:_u128 unsigned __int128_i128 __int128

减号字符不是UDL的一部分,但是应用于UDL结果的一元减号运算符。

因此,对于-ddddd_i128(其中d是数字),UDL会计算带有正值__int128已签名 ddddd,然后编译器将对其应用一元减号运算符。到目前为止一切都很好。

问题在于-170…128_i128(应该是__int128的有效值):
UDL计算已签名 __int128正数170…128,它位于__int128范围之外,导致未定义行为(带符号整数溢出)。

使用UDL表示此数字常量的任何解决方案?


我的UDL被声明(现在只是一个非constexpr, loopy 版本)(它们是原始文字):

unsigned __int128 operator"" _u128(char const *str);
__int128 operator"" _i128(char const *str);

一些用法:

  1000000000000000000000000000000000_i128
  -1000000000000000000000000000000000_i128
  -170141183460469231731687303715884105728_i128 // <-- this has UB
  170141183460469231731687303715884105727_u128
  340282366920938463463374607431768211455_u128

我知道有一些方法可以用各种方式定义常量-170…728,比如位移,数学运算,但我希望能够以一致的方式创建它,例如:我不想要这种情况:你可以使用这个UDL创建任何常量,除了-170…728_i128,你必须使用额外的技巧。

1 个答案:

答案 0 :(得分:6)

这实际上与实现<limits.h>时实现者所遇到的问题相同:INT_MIN无法(在典型的32位系统上)定义为-2147483648。它可以(通常)定义为(-2147483647 - 1)。你必须做类似的事情。可能没有任何方法可以用一个否定运算符和字面来表示最负数,但这没关系:根本不需要它。