C中的签名与未签名操作

时间:2011-03-05 03:37:35

标签: c unsigned

非常简单的问题:

我有一个程序在整数和长期内进行大量的数学计算。为了适应额外的一点,我做了长长的无符号,因为我只处理正数,现在可以得到更多的值。

奇怪的是,这给了我15%的性能提升,我证实这只是让所有长长的未签名。

这可能吗?使用无符号数字,数学运算真的更快吗?我记得读过没有区别,编译器会自动选择最快的方式,无论是签名还是未签名。这个15%的提升真的来自于使vars无符号,还是可能是我的代码中的其他因素?

并且,如果真的是因为使得vars无符号,我是否应该将所有内容(甚至是ints)设置为无符号,因为我从不需要负数,如果我可以保存它,则每一秒都很重要。

4 个答案:

答案 0 :(得分:12)

在某些操作中,有符号整数更快,而在其他操作中,无符号整数更快:

  • 在C中,可以假定有符号整数运算不包装。例如,编译器将在循环优化中利用这一点。比较可以类似地进行优化。 (如果你不指望这个,这也会导致细微的错误。)

  • 另一方面,无符号整数没有这个假设。但是,不必处理符号对于某些操作来说是一个很大的优势,例如:除法。通过2的常数幂进行的无符号除法是一个简单的移位,但是(取决于你的舍入规则)对于负数有一个有条件的除1。

就个人而言,我养成只使用无符号整数的习惯,除非我真的确实有一个需要签名的值。性能与正确性无关。

你可能会看到长效放大的效果,在我的情况下(我猜是)是64位。 CPU通常没有单一指令处理这些类型(在32位模式下),因此签名操作的轻微增加的复杂性将更加明显。

答案 1 :(得分:2)

在32位处理器上,模拟64位整数运算;使用unsigned代替signed意味着仿真库不需要做额外的工作来传播进位等。

答案 2 :(得分:2)

有三种情况,编译器会关心变量是有符号还是无符号:

  1. 当变量转换为更长的类型时
  2. 应用比较运算符(大于等)时
  3. 可能发生溢出

在某些机器上,将签名变量转换为更长的类型需要额外的代码;在其他机器上,转换可以作为“加载”或“移动”指令的一部分执行。

有些机器(主要是小型嵌入式微控制器)需要更多指令才能执行有符号与无符号无符号比较,但大多数机器都有完整的有符号和无符号比较指令数组。

当无符号类型发生溢出时,编译器可能必须添加代码以确保实际发生定义的行为。签名类型不需要这样的代码,因为标准允许在没有此类代码的情况下可能发生的任何代码。

答案 3 :(得分:1)

如果编译器未签名或签名,则编译器不会选择。但是,是的,从理论上讲,unsigned with unsignedsigned with signed更快。如果你真的想减慢速度,你会选择signed with unsigned。更糟糕的是:floats with integers

当然,这取决于处理器。