为什么 C 和 C++ for 循环使用 int 而不是 unsigned int?

2024-03-04

这是一个相当愚蠢的问题,但为什么int常用来代替unsigned int在 C 或 C++ 中为数组定义 for 循环时?

for(int i;i<arraySize;i++){}
for(unsigned int i;i<arraySize;i++){}

我认识到使用的好处int当做数组索引以外的事情时以及使用 C++ 容器时迭代器的好处。仅仅是因为循环数组时并不重要吗?或者我应该避免所有这些并使用不同的类型,例如size_t?


Using int从逻辑角度来看,对数组进行索引更正确。

unsignedC 和 C++ 中的语义并不真正意味着“非负”,但它更像是“位掩码”或“模整数”。

了解原因unsigned不是“非负”数的好类型请考虑这些完全荒谬的陈述:

  • 将一个可能为负的整数与一个非负整数相加,得到一个非负整数
  • 两个非负整数之差始终是非负整数
  • 将非负整数乘以负整数,得到非负结果

显然上面的短语都没有任何意义...但这就是 C 和 C++ 的方式unsigned语义确实有效。

实际上使用一个unsigned容器大小的类型是 C++ 的一个设计错误,不幸的是我们现在注定要永远使用这个错误的选择(为了向后兼容)。您可能喜欢“无符号”这个名称,因为它与“非负”类似,但该名称无关紧要,重要的是语义......并且unsigned离“非负”还很远。

因此,在对向量上的大多数循环进行编码时,我个人首选的形式是:

for (int i=0,n=v.size(); i<n; i++) {
    ...
}

(当然假设向量的大小在迭代过程中没有改变,并且我实际上需要主体中的索引,否则for (auto& x : v)...更好)。

这逃离unsigned尽快使用纯整数的优点是可以避免由于以下原因而导致的陷阱unsigned size_t设计错误。例如考虑:

// draw lines connecting the dots
for (size_t i=0; i<pts.size()-1; i++) {
    drawLine(pts[i], pts[i+1]);
}

如果上面的代码会出现问题pts向量为空,因为pts.size()-1在这种情况下是一个巨大的无意义数字。处理表达式 wherea < b-1不等于a+1 < b即使对于常用的值也就像在雷区跳舞一样。

从历史上看,拥有的理由size_t无符号是为了能够使用值的额外位,例如数组中能够有 65535 个元素,而不是 16 位平台上的 32767 个元素。在我看来,即使在那个时候,这种错误的语义选择所带来的额外成本也是不值得的(如果现在 32767 个元素还不够,那么 65535 个元素无论如何也不会足够长)。

无符号值非常有用,但不能用于表示容器大小或索引;对于大小和索引,常规有符号整数效果更好,因为语义正是您所期望的。

当您需要模算术属性或想要在位级别工作时,无符号值是理想的类型。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 C 和 C++ for 循环使用 int 而不是 unsigned int? 的相关文章

随机推荐