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

Integer overflow with UDL (user defined literal) for __int128 @ min negative value

本文关键字:文字 溢出 整数 定义 int128@min UDL 用户      更新时间:2023-10-16

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

  • −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

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

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

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

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

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

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


我的UDL是声明的(目前只是一个非常常量表达式,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,你必须使用额外的技巧。

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