【问题标题】:When to use unsigned values over signed ones?何时使用无符号值而不是有符号值?
【发布时间】:2008-08-02 03:34:44
【问题描述】:

什么时候适合使用无符号变量而不是有符号变量?在for 循环中呢?

我听到了很多关于这个的意见,我想看看是否有任何类似的共识。

for (unsigned int i = 0; i < someThing.length(); i++) {  
    SomeThing var = someThing.at(i);  
    // You get the idea.  
}

我知道 Java 没有无符号值,这一定是对 Sun Microsystems' 部分的有意识决定。

【问题讨论】:

  • 我觉得这很有帮助:codemines.blogspot.ca/2007/10/…
  • 我认为这个问题是基于意见的。提供的代码在这两种情况下都可以正常运行,因此您可以同时使用这两种情况。除了性能方面的原因(到目前为止,还没有真正涉及性能的答案),这只是个人品味。

标签: language-agnostic types


【解决方案1】:

我很高兴在这个主题上找到 a good conversation,因为我之前并没有真正考虑过。

总而言之,如果您要对变量进行算术运算(例如在典型的 for 循环案例中),签名是一个很好的通用选择 - 即使您完全确定所有数字都是正数。

无符号在以下情况下开始变得更有意义:

  • 您将执行按位操作,例如遮罩,或
  • 迫切需要利用符号位获得额外的正数范围

就个人而言,我喜欢签名,因为我不相信自己会保持一致并避免混合两种类型(就像文章警告的那样)。

【讨论】:

  • 稍后在该线程中,表明unsigned 在检测不受信任的输入中的溢出方面非常出色。不幸的是,为这个难题提出的“答案”并不是那么好。我的是 template&lt;size_t limit&gt; bool range_check_sum( unsigned a, unsigned b ) { return (a &lt; limit) &amp;&amp; (b &lt; limit - a); } 如果有人使用签名类型有类似简单直接的答案,我很乐意看到。
【解决方案2】:

在上面的示例中,当 'i' 始终为正数并且更高的范围将是有益的时,无符号将很有用。就像您使用“声明”语句一样,例如:

#declare BIT1 (unsigned int 1)
#declare BIT32 (unsigned int reallybignumber)

尤其是当这些值永远不会改变时。

但是,如果您正在执行一个会计程序,其中人们对他们的钱不负责任并且经常处于亏损状态,那么您肯定会想要使用“签名”。

我同意圣徒的观点,但一个好的经验法则是使用带符号的,C 实际上默认使用它,所以你被覆盖了。

【讨论】:

    【解决方案3】:

    我认为,如果您的业务案例表明负数无效,您会希望显示或抛出错误。

    考虑到这一点,我最近才在处理二进制文件中的数据并将数据存储到数据库中的项目时发现了无符号整数。我故意“破坏”二进制数据,最终得到负值而不是预期的错误。我发现即使转换了值,但该值对我的业务案例无效。
    我的程序没有出错,我最终将错误的数据输入数据库。如果我使用uint 并让程序失败,那就更好了。

    【讨论】:

      【解决方案4】:

      当您比较有符号和无符号类型时,C 和 C++ 编译器会生成警告;在您的示例代码中,您不能使循环变量无符号并让编译器生成没有警告的代码(假设上述警告已打开)。

      当然,您编译时会一直出现警告,对吧?

      而且,您是否考虑过使用“将警告视为错误”进行编译以更进一步?

      使用有符号数字的缺点是容易使它们重载,例如,值 0->n 是菜单选择,-1 表示未选择任何内容 - 而不是创建具有两个变量的类,一个表示是否选择了某些内容,另一个表示该选择是什么。在不知不觉中,您正在到处测试负数,编译器抱怨您希望如何将菜单选择与您拥有的菜单选择数量进行比较——但这很危险,因为它们是不同的类型.所以不要那样做。

      【讨论】:

        【解决方案5】:

        size_t 通常是一个不错的选择,如果您使用的是 STL 类,size_type

        【讨论】:

        • 仅当您处理以字节为单位的大小时。
        • @mk12 标准库容器公开了size_type 成员的元素计数,而不仅仅是字节。如果可用,应该使用它而不是 std::size_t,但暗示以 size_t 开头的任何内容都只能表示字节是不准确的。
        猜你喜欢
        • 1970-01-01
        • 2015-05-11
        • 1970-01-01
        • 2012-10-02
        • 1970-01-01
        • 2015-10-31
        • 2013-03-27
        • 2011-10-11
        • 1970-01-01
        相关资源
        最近更新 更多