大小应该使用有符号整数还是无符号整数?

Posted

技术标签:

【中文标题】大小应该使用有符号整数还是无符号整数?【英文标题】:Should signed or unsigned integers be used for sizes? 【发布时间】:2017-11-14 10:33:37 【问题描述】:

标准库vector::size() 给出一个size_t,一个无符号数。在 CppCon 的一次演讲中,我听到有人(是 Chandler Carruth 吗?)说这很不幸,应该使用有符号整数。

背景是没有为有符号整数定义溢出,因此编译器有更多的余地。在一次谈话中,Carruth 展示了 uint8_t 作为 bzip2 中的 for 循环索引如何在 x86 上创建比 int8_t 更多的机器指令,因为它必须使用掩码和移位显式模拟溢出。

在我现在处理的代码中,某些大小是严格正数的。这些表示为size_t。这看起来不错,因为这表明它们不可能是负面的。另一方面,不需要定义的模运算,所以只要有符号整数足够大(我们去像 200),无符号整数就会有错误的接口来进行我们想要的算术运算。

在代码中的某个点,存在从 0 到这个大小的循环。然后减去循环索引,取绝对值。

当我使用更现代的 GCC 7 编译它时,它无法解决 std::abs 的正确重载,因为显然 size_t - size_t 给出了模棱两可的值。我已将代码更改为在循环索引中使用 int

for (int t1 = 0; t1 < Lt; t1++) 
  for (int t2 = 0; t2 < Lt; t2++) 

现在abs(t1 - t2) 工作正常。但是比较 t1 &lt; Lt 会发出警告,因为它是有符号数和无符号数之间的比较。

什么是正确的方法?

    对非负数使用无符号整数,然后在需要减法时使用static_cast&lt;int&gt;()。 循环索引使用有符号整数,容器大小使用无符号整数。然后在比较中使用static_cast&lt;int&gt;。 在任何地方都使用有符号整数。当其他库返回无符号整数时,只需在此处使用static_cast&lt;int&gt; 即可满足警告。

【问题讨论】:

如果你想要一个有符号的值,使用ssize_t(注意额外的s)而不是int This 可能很有趣。 @Martin Ueding 所有这些考虑都没有意义。只是忽略他们。如果某些实体不能否定,则使用适当的无符号类型。 @VladfromMoscow:是的。然后执行for (unsigned int i=0; i&lt;size-1; i++) 之类的错误 - 如果大小为 0,则循环 UINT_MAX 次。加上无符号整数禁用某些优化。这是一个糟糕的建议。 @juanchopanza:我想过这个,但没有写。不涉及模算术,在 Carruths 演讲之后,我认为无符号整数用于模算术而不是非负值。 【参考方案1】:

“在一次谈话中,Carruth 展示了 uint8_t 作为 bzip2 中的 for 循环索引如何在 x86 上创建比 int8_t 更多的机器指令,因为它必须使用掩码和移位显式模拟溢出。”

好吧,如果您可以使用任一类型,则 for-range 必须限制为 [0, 127]。只需使用int 作为索引类型,然后。它根据定义是基本数学运算的自然类型,通常很好地映射到 CPU 寄存器。

使用针对最小存储优化的类型不会生成最快的数学运算,不会。这并不奇怪。您无法根据此类有缺陷的设置得出关于签名与未签名的结论。

size_t - size_t 给出了模棱两可的值”

嗯,它没有,但它确实使用了模运算。 size_t(1)-size_t(2)==size_t(-1),但 size_t(-1) 是最大可能值。这直接来自模块化数学的定义:x-1 &lt; x,除非x-1 环绕,因为x==0。 (或等价于x+1&gt;xx+1==0 除外)

因此调用abs(size_t(x)) 也毫无意义,因为每个size_t 值都是正数。将有符号整数与size_t 进行比较同样会带来意想不到的后果。明确的演员表是好的,因为它们使后果清楚。

但是没有通用的解决方案可以自动确定应该应用哪个演员表。如果可以发明机械规则,我们可以将该规则留给编译器。我们没有,因为我们做不到。作为程序员,您必须以数字方式考虑每种情况。

【讨论】:

以上是关于大小应该使用有符号整数还是无符号整数?的主要内容,如果未能解决你的问题,请参考以下文章

有符号整数与无符号整数

关于:有符号与无符号整数的大小比较

C中的无符号整数在java中的处理

使用 AVX 的有符号/无符号整数的最小值

QImage 格式 Format_ARGB32 数据是有符号还是无符号整数?

如何忽略“有符号和无符号整数表达式之间的比较”?