是否有理由将无符号类型用于非负常数?

时间:2018-04-13 19:36:06

标签: c++

我在代码审查中看到了类似的内容:

constexpr int64_t SOME_MAX = 2147483647;

我最初的想法是添加一个请求,使其成为无符号类型,例如uint64_t。我的习惯是使用无符号整数来表示我知道应该总是积极的价值观。但后来我想知道这是否为常数增加了任何实际价值。有没有理由在c ++中将非负的const设置为unsigned int类型?

3 个答案:

答案 0 :(得分:5)

  

有没有理由在c ++中将非负的const设置为unsigned int类型?

对常量使用无符号类型的一个原因是它表示一个位集。

另一个原因是它表示类型的最大值。

要表示特定的普通数字必须是非负数,您可以使用断言。仅表示,例如对于正式参数,您可以使用类型名称别名,例如using Positive_int = int;。要对给定的数字使用强制执行,您可以定义范围检查类型。

将普通数字常量定义为无符号类型可能会无意中将操作符参数提升为unsigned,并带有环绕。这种不受欢迎的影响从无到有,到烦人的编译器警告,到不正确的结果。支付范围指示是一个很高的代价,通过类型名称别名可以更清楚地传达。

答案 1 :(得分:4)

混合有符号和无符号类型会产生编译器警告和意外结果。

例如,给定int x = -1,表达式为:

if ( x < SOME_MAX )
如果trueSOME_MAX

将为int64_t 如果falseSOME_MAX

将为uint64_t,因为x将隐式转换为无符号。

请参阅Signed/unsigned comparisons

你不应该只是因为你知道这个值是非负的而无法使用常量。

您应该选择是否使用它将使用的上下文无符号。

答案 2 :(得分:1)

  

是否有任何理由将非负const设置为unsigned int   输入c ++?

不应使用无符号来表示一个数字不应为负数的事实,因为它是谎言; unsigned int不能为负数,但如果您尝试将其设置为负数,语言也不会抱怨。更糟糕的是,它会默默地将其变成一个巨大的正数。甚至可以防止错误检测

unsigned int f() { return 1; }
unsigned int g() { return 2; }
unsigned int x = f() - g();
assert(x >= 0); // futile

有符号整数允许您检测错误:

int f() { return 1; }
int g() { return 2; }
int x = f() - g();
assert(x >= 0);

话虽如此,您可能正在处理已使用无符号整数的其他代码来表示不应该为负的数字。不幸的是,这包括C ++标准库,由于历史原因,它使用无符号大小。在这种情况下,使用无符号数字也是可以接受的折衷方案。

至于你的代码示例,

constexpr int64_t SOME_MAX = 2147483647;

我可以想出两种更好的表达方式:

auto constexpr some_max = 2147483647;

auto constexpr some_max = std::numeric_limits<int32_t>::max();