当我想否定一些类型std::size_t
时,我通常会这样做-static_cast<int>(number)
。但是,我知道该数字可能不适合int
. 所以,我的问题是什么是安全的便携方式来做到这一点?
4 回答
没有安全的便携式方法可以做到这一点。
size_t
是无符号类型。不能保证有任何有符号整数类型大到足以容纳 的最大值size_t
。
如果您能够假设您要否定的值不是太大,您可以将其转换为long long
(如果您的编译器支持它)或long
(如果它不支持):
size_t s = some_value;
long long negative_s = -(long long)s;
如果您担心溢出,可以在进行转换之前比较s
to的值。LLONG_MAX
-static_cast<int>(number)
是安全的;的结果static_cast
是实现定义的,如果它不适合int
.
要检测结果是否不适合:
(number <= std::numeric_limits<int>::max()) ? -static_cast<int>(number) : ...
安全的方法检查变量是否适合相应的有符号类型:
typedef std::size_t my_uint;
typedef typename std::make_signed<my_uint>::type my_int;
my_uint n = /* ... */;
if (n > std::numeric_limits<my_int>::max()) { /* Error! */ }
my_int m = -static_cast<my_int>(n);
你需要#include <limits>
和<type_traits>
。
(或者把所有东西都放在一行里:)
if (n > std::numeric_limits<typename std::make_signed<decltype(x)>::type>::max()) { /* Error! */ }
我认为您有一个固有的问题,因为您不可能否定 a std::size_t
using的上半部分范围内的值std::ssize_t
,因为 astd::ssize_t
只能描述范围内的一半值std::size_t
。例如,如果您的unsigned char
值为 255,则永远无法获得signed char
-255 的值……您需要更大的类型,例如signed short
. 如果std::size_t
是您平台的最大集成容器,那么您根本无法以“负”格式描述这些值,而无需指定一些自定义数据类型,例如struct
带有用于指定符号的额外标志变量的a价值。那当然不再是“便携式”...