为什么 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? 的相关文章

  • 删除文件的最后 10 个字符

    我想删除文件的最后 10 个字符 说一个字符串 hello i am a c learner 是文件内的数据 我只是希望该文件是 hello i am a 文件的最后 10 个字符 即字符串 c learner 应在文件内消除 解决方案 将
  • 结构化绑定中缺少类型信息

    我刚刚了解了 C 中的结构化绑定 但有一件事我不喜欢 auto x y some func is that auto正在隐藏类型x and y 我得抬头看看some func的声明来了解类型x and y 或者 我可以写 T1 x T2 y
  • 在 xaml 中编写嵌套类型时出现设计时错误

    我创建了一个用户控件 它接受枚举类型并将该枚举的值分配给该用户控件中的 ComboBox 控件 很简单 我在数据模板中使用此用户控件 当出现嵌套类型时 问题就来了 我使用这个符号来指定 EnumType x Type myNamespace
  • 类型中的属性名称必须是唯一的

    我正在使用 Entity Framework 5 并且有以下实体 public class User public Int32 Id get set public String Username get set public virtual
  • C++11 删除重写方法

    Preface 这是一个关于最佳实践的问题 涉及 C 11 中引入的删除运算符的新含义 当应用于覆盖继承父类的虚拟方法的子类时 背景 根据标准 引用的第一个用例是明确禁止调用某些类型的函数 否则转换将是隐式的 例如最新版本第 8 4 3 节
  • std::vector 与 std::stack

    有什么区别std vector and std stack 显然 向量可以删除集合中的项目 尽管比列表慢得多 而堆栈被构建为仅后进先出的集合 然而 堆栈对于最终物品操作是否更快 它是链表还是动态重新分配的数组 我找不到关于堆栈的太多信息 但
  • 随着时间的推移,添加到 List 变得非常慢

    我正在解析一个大约有 1000 行的 html 表 我从一个字符串中添加 10 个字符串 td 每行到一个list td
  • -webkit-box-shadow 与 QtWebKit 模糊?

    当时有什么方法可以实现 webkit box shadow 的工作模糊吗 看完这篇评论错误报告 https bugs webkit org show bug cgi id 23291 我认识到这仍然是一个问题 尽管错误报告被标记为RESOL
  • 如何使从 C# 调用的 C(P/invoke)代码“线程安全”

    我有一些简单的 C 代码 它使用单个全局变量 显然这不是线程安全的 所以当我使用 P invoke 从 C 中的多个线程调用它时 事情就搞砸了 如何为每个线程单独导入此函数 或使其线程安全 我尝试声明变量 declspec thread 但
  • C++ 多行字符串原始文字[重复]

    这个问题在这里已经有答案了 我们可以像这样定义一个多行字符串 const char text1 part 1 part 2 part 3 part 4 const char text2 part 1 part 2 part 3 part 4
  • 访问外部窗口句柄

    我当前正在处理的程序有问题 这是由于 vista Windows 7 中增强的安全性引起的 特别是 UIPI 它阻止完整性级别较低的窗口与较高完整性级别的窗口 对话 就我而言 我想告诉具有高完整性级别的窗口进入我们的应用程序 它在 XP 或
  • 方程“a + bx = c + dy”的积分解

    在等式中a bx c dy 所有变量都是整数 a b c and d是已知的 我如何找到整体解决方案x and y 如果我的想法是正确的 将会有无限多个解 由最小公倍数分隔b and d 但我只需要一个解决方案 我可以计算其余的 这是一个例
  • 为什么 isnormal() 说一个值是正常的,而实际上不是?

    include
  • 编译时展开 for 循环内的模板参数?

    维基百科 here http en wikipedia org wiki Template metaprogramming Compile time code optimization 给出了 for 循环的编译时展开 我想知道我们是否可以
  • 有没有办法让 doxygen 自动处理未记录的 C 代码?

    通常它会忽略未记录的 C 文件 但我想测试 Callgraph 功能 例如 您知道在不更改 C 文件的情况下解决此问题的方法吗 设置变量EXTRACT ALL YES在你的 Doxyfile 中
  • 在 WPF 中使用 ReactiveUI 提供长时间运行命令反馈的正确方法

    我有一个 C WPF NET 4 5 应用程序 用户将用它来打开某些文件 然后 应用程序将经历很多动作 读取文件 通过许多插件和解析器传递它 这些文件可能相当大 gt 100MB 因此这可能需要一段时间 我想让用户了解 UI 中发生的情况
  • C++ 继承的内存布局

    如果我有两个类 一个类继承另一个类 并且子类仅包含函数 那么这两个类的内存布局是否相同 e g class Base int a b c class Derived public Base only functions 我读过编译器无法对数
  • 当文件流没有新数据时如何防止fgets阻塞

    我有一个popen 执行的函数tail f sometextfile 只要文件流中有数据显然我就可以通过fgets 现在 如果没有新数据来自尾部 fgets 挂起 我试过ferror and feof 无济于事 我怎样才能确定fgets 当
  • Mono 应用程序在非阻塞套接字发送时冻结

    我在 debian 9 上的 mono 下运行一个服务器应用程序 大约有 1000 2000 个客户端连接 并且应用程序经常冻结 CPU 使用率达到 100 我执行 kill QUIT pid 来获取线程堆栈转储 但它总是卡在这个位置
  • 使用 WGL 创建现代 OpenGL 上下文?

    我正在尝试使用 Windows 函数创建 OpenGL 上下文 现代版本 基本上代码就是 创建窗口类 注册班级 创建一个窗口 choose PIXELFORMATDESCRIPTOR并设置它 创建旧版 OpenGL 上下文 使上下文成为当前

随机推荐