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

bol*_*lov 7 c++ integer-overflow int128 user-defined-literals c++11

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

  • ?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位有符号整数(__int128 in gcc)的最小值和最大值.

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

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

因此对于a -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);
Run Code Online (Sandbox Code Playgroud)

一些用法:

  1000000000000000000000000000000000_i128
  -1000000000000000000000000000000000_i128
  -170141183460469231731687303715884105728_i128 // <-- this has UB
  170141183460469231731687303715884105727_u128
  340282366920938463463374607431768211455_u128
Run Code Online (Sandbox Code Playgroud)

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

小智 6

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

  • @bolov:`-2147483648`不是文字.它是一个由文字"2147483648"组成的表达式,其中应用了一元"-`运算符.一元`-`可以溢出. (2认同)