内置与size_t类型一起使用的正确整数溢出是什么

时间:2018-01-29 01:54:33

标签: c integer-overflow

例如:

size_t x;
...
__builtin_uaddll_overflow(x,1,&x);

无论编译器实现如何,上面的代码都能正确防止整数溢出吗?

到目前为止我所知道的:

  • reference表示size_t是无符号类型。
  • 根据此discussiontypedef unsigned long size_t;可用于定义size_t

reference列出的功能是否始终正确?或者它必然取决于具体实施?如果是这样,我怎么能以编程方式选择正确的函数?

1 个答案:

答案 0 :(得分:6)

__builtin_uaddll_overflow()
  

无论编译器实现如何,上面的代码都能正确防止整数溢出吗?

没有。 __builtin_uaddll_overflow()不是指定的C运算符,也不是C标准库函数。它限制代码选择编译器。 C未指定SIZE_MAX的功能。

相反,只需针对便携式实现与size_t进行比较。无论unsignedunsigned longunsigned还是其他无符号类型相同,都是可移植的,甚至比size_t x; size_t y; if (SIZE_MAX - x < y) Overflow(); else size_t sum = x + y; 更宽或更窄。< / p>

some_unsigned_type

这适用于各种 unsigned 类型 - 甚至是狭窄的类型。始终使用相同的some_unsigned_type x; some_unsigned_type y; if (some_unsigned_type_MAX - x < y) Overflow(); else some_unsigned_type sum = x + y;

unsigned

使用至少与some_at_least_unsigned_type x; some_at_least_unsigned_type y; some_at_least_unsigned_type sum = x + y; // overflow behavior well defined if (sum < x) { Overflow(); } else { // continue with non-overflowed sum } 一样宽的无符号类型时,代码可以使用以下内容。

size_t

size_t的情况下,unsigned 非常普遍宽于或宽于unsigned,但未指定为x + y

上述内容通常适用于无符号类型,然后比int更窄。然而,int1u*x + y数学完成,然后独角兽平台可以溢出0u + x + y数学。 some_unsigned_typeunsigned强制数学始终以无符号完成,无论1u*是否比some_unsigned_type x; some_unsigned_type y; some_unsigned_type sum = 1u*x + y; // overflow behavior well defined if (sum < x) { Overflow(); } else { // continue with non-overflowed sum } 更窄/更宽。一个好的编译器会发出不执行实际size_t x; size_t sum = x + 1u; // overflow behavior well defined if (sum == 0) { Overflow(); } else { // continue with non-overflowed sum } 乘法的优化代码。

{{1}}

或者在OP的第1个示例中,确保无符号数学添加:

{{1}}