有关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语言中有符号/无符号数混合运算的小问题

http://blog.csdn.net/supreme42/article/details/7401254 有关C语言中有符号/无符号数混合运算的小问题 分类: C语言知...
  • wangyin159
  • wangyin159
  • 2014年08月15日 14:10
  • 336

c语言之无符号/有符号数加减法运算

c语言之无符号/有符号数加减法运算 转自:http://www.360doc.com/content/12/1129/15/1317564_250977880.shtml 1.加减运算指令是不...
  • xlhcgd
  • xlhcgd
  • 2015年08月28日 17:09
  • 4688

关于C语言中无符号与有符号数之间运算问题

int array[] = {23, 34, 12, 17, 204, 99, 16}; #define TOTAL_ELEMENTS (sizeof(array)/sizeof(array[0]))...
  • talent_CYJ
  • talent_CYJ
  • 2016年04月20日 10:45
  • 736

C语言中有符号数与无符号数相加

计算机中的加法运算是通过加数补码相加实现的。 程序中,a为无符号整型数,其补码为0000 0001(方便起见,这里仅用8位表示,下文同理),起始位的“0”表示数值;b为有符号整型数,其补码为1111 ...
  • ZM970307
  • ZM970307
  • 2017年05月06日 22:53
  • 1224

C语言系列(二)有符号数和无符号数详解

1、你自已决定是否需要有正负:就像我们必须决定某个量使用整数还是实数,使用多大的范围数一样,我们必须自已决定某个量是否需要正负。如果这个量不会有负值,那么我们可以定它为带正负的类型。在计算机中,可以区...
  • u011974987
  • u011974987
  • 2016年08月07日 15:39
  • 7172

C语言中的有符号数与无符号数

1.  C语言支持所有整型数据类型的有符号和无符号运算,尽管C语言标准并没有指定用哪种方式来表示有符号整数,但是几乎所有的     机器都使用补码。 2.  C语言中默认的整形数据是有符号的...
  • ben_xiao_hai
  • ben_xiao_hai
  • 2014年08月14日 07:53
  • 776

FPGA开发之有无符号运算

有符号运算和无符号运算的问题 关于误导 在MIPS中文版指令集上提到一点,希望大家引起注意:ADDU的”U”不是无符号,而是指不考虑溢出的加法,所以ADDI和ADD和ADDU实际上在ALU用的同...
  • u012727853
  • u012727853
  • 2015年01月06日 15:56
  • 983

C语言中无符号数运算判断溢出

对于无符号加法运算,当执行C程序时,不会将溢出作为错误而发信号。例如要计算s = x + y;如果溢出则会得到结果s = (x + y) %2w或者s = x + y - 2w(w 是机器中无符号的最...
  • ljg888
  • ljg888
  • 2012年10月01日 10:16
  • 4194

c语言中有符号和无符号数据类型的区别

最大是0---65535,8位2进制数,有符号也是8位2进制,只不过第一位用来表示符号了,所以有符号的范围是-32768---32767....
  • gogoky
  • gogoky
  • 2014年10月03日 20:02
  • 5953

C中的有符号数和无符号数之间的转换

在C语言中,数字常量如果没有后缀‘U'或'u',则默认为是有符号。 同类型整数之间的类型转换。 有符号数和无符号数之间进行类型转换。 有符号数和无符号数在一起进行运算时,要首先将有符号数转换为无符号数...
  • fhyangchina
  • fhyangchina
  • 2017年02月16日 08:45
  • 2806
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:有关C语言中有符号/无符号数混合运算的小问题
举报原因:
原因补充:

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