这两天的工作需要涉及到对无符合数,有符号数作混合运算。

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

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

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

  1. C语言中有符号数和无符号数的问题

    C语言中有符号数和无符号数的问题 项目说明     考虑下列代码, 这段代码试图计算数组a中所有元素的和, 其中元素的数量由参数length给出: /* WARNING: This is buggy ...

  2. C语言中有符号与无符号

    --事物的难度远远低于对事物的恐惧! 经过养成记1,已经有一个很好的开端,但革命尚未成功,坚持就是胜利!现在我们来分析下C语言中的有符号数与无符号数.我们知道,计算机只能识别二进制0和1,那么我们在程 ...

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

    欢迎探讨,感觉写的不能达意. 1 读了<深入理解计算机系统>后,觉得下面{{{{  }}}}}所有内容可以总结为如下,无符号数与有符号数间的转换就是数值在内存的位模式不变,改变的是对位模式 ...

  4. 有符号数与无符号数之间运算问题探究

    文章目录 有符号数与无符号数之间运算问题 例子: 问题探究: unsigned int变量跟int类型的变量运算时得出的结果是什么类型的? 逐步思考: 代码分析: 问题总结 例:1: 例2: 无符号和 ...

  5. c语言 有符号数与0作比较大小,C语言中有符号数与无符号数能否进行比较运算...

    无符号数和有符号数是不能进行比较运算的,否则可能会出现意想不到的错误,且极难检查出来! 首先肯几个例子(假设在32位的机器上): 1         1. 0 == 0U 2         2. - ...

  6. printf()、sprintf()、vprintf()、vsprintf()、有符号|无符号数

    http://sumsung753.blog.163.com/blog/static/14636450120112151092934/ 一.printf() printf()函数优点在于可以格式化输出 ...

  7. C语言中有符号整数中0的表示方式

    如何表示有符号整数取决于硬件,而不是C语言本身.也许表示有符号数最简单的方式式用1位(如,高阶位:即二进制方式存储数据时的最高位)存储符号,只剩下7位表示数字本身(假设存储在1个字节中).用这种符号量 ...

  8. Verilog 和VHDL有符号数和无符号数相关运算

    目录 一.Verilog有无符号数运算 1.有符号数和有符号数的加减运算(输入和输出为原码) 2.无符号数和有符号数的加减运算(输入和输出为原码) 3.有符号数和有符号数的乘法(输入和输出为原码) 二 ...

  9. c++中的有符号数与无符号数一起运算

    先说自己看书与调试的结论:在有符号与无符号一起运算的时候,正数就是正数,负数就是负数,计算机正常做加减运算,但是运算的结果会被程序当成无符号数. 验证过程: 1.测试代码 test.cpp #incl ...

最新文章

  1. C++利用二级指针做函数形参来进行修改实参的实例分析
  2. [C#项目开源] MongoDB 可视化管理工具 (2011年10月-至今)
  3. 开机动画适配方案_2020 年 4 月前 App 启动画面、屏幕调整需按要求适配,否则存拒审风险!...
  4. c语言双引号和单引号的区别
  5. ⼤海捞针 —— Scan
  6. MySQL中序列的作用_MySql中序列的应用和总结
  7. php火的原因,重燃你的PHP安全之火
  8. JavaScript Object 及相关操作
  9. 05. Know what functions C++ silently writes and calls
  10. 系统调用之Write
  11. 商城系统功能多不是运营的关键,但是功能多,真香!
  12. java怎么销毁session_Java中session的销毁
  13. word转HTML 基本版
  14. 零基础如何学习java?
  15. ERROR Error validating install location: Distro ‘rhe17‘ does not exist in our dictionary
  16. 模拟地铁自动售票系统C语言,基于PLC的地铁自动售票机控制系统设计.doc
  17. 一个设计低通巴特沃斯数字滤波器的实例
  18. 安卓:Day5 列表视图
  19. 红帽8搭建httpd
  20. [Ext4] Ext4文件系统分析系列文章

热门文章

  1. linux查询所建文件夹,linux中的文件和文件夹的新建、查询、删除
  2. 原生js增加或者删除class
  3. openstack-5:安装rabbitmq
  4. 学习不一样的vue实战(1): 环境搭建
  5. java基础:数据类型
  6. Redhat安装tftp的方法
  7. perl学习笔记(9)
  8. Infobright 数据仓库心得总结
  9. DHCP服务器-配置
  10. JPA规范的主要内容