有关C语言中有符号/无符号数混合运算的小问题

转载 2012年03月28日 00:47:02
这两天的工作需要涉及到对无符合数,有符号数作混合运算。

作了一些实验,发现自己写了这么多年的程序,以前对于符号数计算相关的理解居然仍存在一些盲点。

有符号数与无符号数混合运算可能有三种混合方式

1。操作数全为有符号数
如:

int a = -1;
int b = 2;
a + b;


2。操作数全为无符号数

如:

unsigned int a = (unsigned int)-1;
unsigned int b = 2;
a + b;


3。操作数混合了有符号数,无符号数
如:

int a = -1;
unsigned int b = 2;
a / b;


情形1和2就不用说了,因为运算中涉及的都是相同符号特征的操作数,计算过程中不会引起歧义。

而对于情形3,由于涉及到了符号特性相异的操作数,情况就有些复杂了。

这里先说一下,对于有些运算操作,是要区分有符号与无符号的情况的。比如有符号的除法与无符号

的除法,有符号的取模运算与无符号的取模运算,其计算语意是不同的,具体来说,有符号的除法在x86

平台上对应的汇编指令是idiv,而无符号的除法对应的则是div

对于另外一些操作运算,则是不区分有符号与无符号的,比如,加法,减法,乘法运算。

对于不同操作符与符号相关的情形可以通过下面的小程序来验证:

int main()
{

signed int n1 = 1;
signed int n2 = 2;
unsigned int u1 = 1;
unsigned int u2 = 2;

signed int a = n1 + n2;
unsigned int ua = u1 + u2;

signed int s = n1 - n2;
unsigned int us = u1 - u2;

signed int m = n1 * n2;
unsigned int um = u1 * u2;

signed int d = n1 / n2;
unsigned int d = u1 / u2;

signed int m = n1 % n2;
unsigned int um = u1 % u2;

return 0;
}

对这一段程序调用 g++ -S,生成相应的汇编文件,就会发现:

加法运算,无论是有符号还是无符号,对应的都是addl指令,

减法
运算,对应的都是subl指令,

乘法
运算,对应的都是imul指令,

有符号除法
运算对应的是idiv指令,无符号除法对应的则是 div指令,

有符号数取模运算会用到idiv指令,无符号取模用的则是div指令。

所以回到初始的问题,情形1和2的行为是容易预期的,因为所有操作数都具有同样的符号特性,直接就

可以得出采用相应符号特性的运算类型。

对于情形3,因为涉及到不同符号数的混合计算,在计算之前需要先对操作数进行规整化的动

作,规整的原则就是如果操作数中存在至少一个无符号数,则所有操作数都被转化为无符号数,

运算操作也采用相应的无符号操作符进行,计算完的结果也是一个无符号数。


举例来说:

(unsigned int)a / (signed int)b
会采用无符号除法进行,其实质相当于

(unsigned int)a / (unsigned int)b

计算结果也是一个无符号数。

再进一步,对于运算-2 / -1,如果采用有符号数运算,结果是1,采用无符号数运算,结果则是0

所以 (signed int)(-2) / (unsigned int)(-1)的结果就是0了。

除法,取模这样的操作符在不同的上下文语境里对应的语义动作也有所不同,而且这种差异还不

同于c++里的操作符重载在语言级别可见,而是要到更底层的汇编语言级别才可见,这多少就有

一些tricky,也容易诱使程序员犯错了。如果有机会我来设计一门语言,我想自己会尽量避免引

入这种tricky的东西的。

相关文章推荐

C陷阱篇之有/无符号数混合时自动类型转换

先看下面代码:     void main()     {       unsigned int i=8;       if(i>=-1)  printf("8>=-1\n");      ...
  • ipmux
  • ipmux
  • 2013年12月14日 11:00
  • 1055

深入理解linux内核自旋锁

自旋锁是一个互斥设备,它只有两个值:“锁定”和“解锁”。它通常实现为某个整数值中的某个位。希望获得某个特定锁得代码测试相关的位。如果锁可用,则“锁定”被设置,而代码继续进入临界区;相反,如果锁被其他人...

有关C语言中有符号/无符号数混合运算的小问题

这两天的工作需要涉及到对无符合数,有符号数作混合运算。 作了一些实验,发现自己写了这么多年的程序,以前对于符号数计算相关的理解居然仍存在一些盲点。 有符号数与无符号数混合运算可能有...

无符号数运算问题——C语言隐式类型转换

要排序几个存了IP的文件,使用ntohl(inet_addr(ip));转成了无符号数,然后使用qsort函数来排序,但发现老是有部分数据没排正确。 经仔细检查,比较函数如下: typedef str...
  • bytxl
  • bytxl
  • 2012年09月07日 11:05
  • 632

C语言 有/无符号数 需要注意的问题

关于溢出问题:有符号数和无符号数都会溢出,都会发生绕回,即从最大下一个就是最小值. 类型转换问题: ANSI C规定在无符号整数和有符号整数之间进行强制类型转换时,位模式不应该改变。类型转换并未改变对...
  • willtin
  • willtin
  • 2016年04月06日 13:06
  • 260

单片机中无符号数运算出现的问题

在单片机编程中,我们经常会用到一些无符号数与有符号数的混合运算,另外我们所用的单片机很有可能是16位或者8位的,这样,编程时所用的一些变量的取值范围会对我们的 运算有所限制.比如说8位的单片机无符号数...
  • DLUTXIE
  • DLUTXIE
  • 2011年08月22日 20:00
  • 3970

C语言中的无符号数

首先来看一道题目:   自己写一遍运行一下,发现打印了“ok”,怪怪的,str2比str1长吗? 为什么呢? 原因是,Char型数组的长度一定是>=0,所以strlen()函数的返回值是一个无符号整数...

有符号数与无符号数之间运算问题

首先我们要先了解一下下面几个概念:(注意一点计算机的操作执行只认1与0,至于像如10001100这样的值是什么值,补码原码,还是其他,由程序员自己解释。)      (1)模:“模”是指一个计量系统的...

有符号数与无符号数之间运算问题

以下实验均在virual c++6中运行通过 这个问题测试是否懂得C语言中的整数自动转换原则,有些开发者懂得极少这些东西。 当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:有关C语言中有符号/无符号数混合运算的小问题
举报原因:
原因补充:

(最多只允许输入30个字)