7

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

  • −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,727作为170…727

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

我为这种数据类型实现了用户定义的文字(原始文字),因为 gcc 不提供定义这种类型的常量的方法:_u128forunsigned __int128_i128for __int128

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

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

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

有什么解决方案可以用 UDL 表示这个数字常数吗?


我的 UDL 被声明(现在只是一个非常量的、循环的版本)(它们是原始文字):

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,你必须使用额外的技巧。

4

1 回答 1

6

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

于 2014-08-05T18:59:43.900 回答