关于符号扩展的一些整理,原文:

http://blog.csdn.net/weizhee/article/details/1351455

http://www.cppblog.com/deercoder/articles/98080.html

http://blog.csdn.net/andy572633/article/details/7322893

最近由于工作需要展望性地研究了一下64位编程。无非就是一些int,long和pointer间转换时的注意事项。如果就兴趣的话可以去搜索一下ILP32和LP64数据模型的相关知识。我略有小得的却是间接地对基本类型间的相互转换加深了认识。这里我想说一下符号扩展的问题。符号扩展不只是在64位编程时应该注意的问题,在32位编程时同样需要注意。请先看下面的例子:

#include int main(void)

{

char c = 1<<7;

short s;

s = c;

printf("%d/n",s);

return 0;

}

由于c是有符号char类型,值是-128,s是有符号short类型,把c赋值给s后,程序输出-128似乎是理所当然的。

那么我们把c改成无符号数,程序变成如下:

#include int main(void)

{

unsigned char c = 1<<7;

short s;

s = c;

printf("%d/n",s);

return 0;

}

c是无符号char类型,值是128,s是有符号short类型,把c赋值给s后,程序输出128似乎是也理所当然的。

当我们让c是有符号的,s是无符号的时候,程序变成如下:

#include int main(void)

{

char c = 1<<7;

unsigned short s;

s = c;

printf("%d/n",s);

return 0;

}

此时程序输出65408,这是为什么呢?原因就在于符号扩展。

让我们来对比一下这3个程序中的c与s的16进制值:

程序1    程序2     程序3

c  0x80     0x80       0x80

s  0xff80   0x0080  0xff80

当负的有符号char转换成有符号short时,符号位要进行扩展,即扩展位是全1而不是全0。

那么 对于程序3,为什么有符号char转换成无符号short也进行了符号扩展呢?其实这里也是有规则的:

当有符号char转换成无符号short时,有符号char首先转换成有符号short,再转换成无符号short。

这样问题才算清晰了,无符号0xff80的值即是65408。

上述规则对于char到long,short到long的转换都是适用的。

C语言中,当不同类型的数据进行运算的时候,就会发生强制或隐式类型转换,通常是低精度的数据类型扩展到高精度的。有些时候,低精度的位数比较少,扩展到高精度的时候,就要在前面补充一些位。那么这些位是补0还是补1呢?这就涉及到无符号扩展和带符号扩展。

扩展的原则是:1.有符号的数据类型,在向高精度扩展时,总是带符号扩展

2.无符号的数据类型,在向高精度扩展时,总是无符号扩展

怎么理解呢?首先来看一道题目,按此题目讲解完你就明白了!

char   ca=128;

unsignedcharucb=128;

unsigned  short   usc=0;

1)usc=ca + ucb;

printf("%x",usc);

2)usc=ca +(unsigned  short)ucb;

printf("%x",usc);

3)usc=(unsignedchar)ca

+ ucb;

printf("%x",usc);

4)usc=ca+(char)ucb;

printf("%x",usc);

问,在1、2、3、4这4种情况下分别输出什么?

分析:

1)对于char类型,有符号,128已经溢出了,其二进制是 1000 0000,第一位会被当成符号位,也是就是说此时它是负数了,它扩展成unsigned short时,带符号位扩展,符号位为1,所以在前方补1,结果是

1111 1111 1000 000。ucb类型为nsignedchar,无符号,二进制是1000

0000,扩展成unsigned shor,无符号扩展,所以补0,结果是0000 0000 1000 0000,。相加结果为 1 0000 0000 0000 0000 由于unsigned

short是二字节,舍弃最前面的1,所以得到0x0,

2)情况和1一样,只是将ucb显示强制转换为unsigned

short,所以得到0x0,

3)ca先强制转换为unsignedchar,仍然是1000

0000,注意此时转换后已经是一个无符号数,所以再往unsigned  short 扩展时,为无符号扩展,结果为0000 0000 1000 0000,ucb扩展后

也是0000

0000 1000 0000,相加结果为 0000 0001 0000 0000,所以结果为0x100

4)ca转为unsigned

short,带符号扩展,为1111 1111 1000 000,ucb先强制转换为char,然后再转为unsigned short,此时也要带符号扩展,所以也是1111

1111 1000 000,两数相加,得到 1 1111 1111 0000 0000 ,所以结果为0xff00

符号扩展和截断的几点认识:

1.符号扩展。。

shortinta= -4;

shortintb= 8;

print_binary(a);

print_binary(b);

unsignedshortintc=a;//类型转换

unsignedintd=a;

print_binary(c);

print_binary(d);

return0;

结果是:

11111111 11111100

00000000 00001000

11111111 11111100

11111111 11111111 11111111 11111100

请按任意键继续. . .

从结果可以看到:

1.类型转换时不改变位的标志的。

2.符号扩展,将一个有符号的扩展的话是符号扩展。从short扩展到int,由于是负数,所以符号扩展,前面的都是111111……

2.截断处理:

inta= -4;

shortintb=a;

intc= 4;

shortintd=c;

print_binary(a);

print_binary(b);

print_binary(c);

print_binary(d)

结果是:

11111111 11111111 11111111 11111100

11111111 11111100

00000000 00000000 00000000 00000100

00000000 00000100

请按任意键继续. . .

发现了,截断高位,不管符号,都要截断高位的部分。

3.乘法和除法:

当存储数据的位数不足以存储乘积的时候,会造成截断误差,通过截断,得到我们的结果不是想要的结果:看下例:

chara= 120;

print_binary(a);

charc= 120;

print_binary(c);

chard=a*c;

cout<< (short)d<

print_binary(d);

inte=a*c;

cout<

print_binary(e);

return0;

结果是:

01111000

01111000

64

01000000

14400

00000000 00000000 00111000 01000000

请按任意键继续. . .

看到了没有,对于一个char类型的数据,如果将两者的乘积还是保存为char,那么就有可能发生截断,产生误差。此例即为说明,而如果将结果用int来保存,可以看到完整的位表示,然后具体的截断也知道了。此时就可以得到正常的结果,因为有足够的位,没有造成损失。。

c语言无符号扩展,C语言中的无符号扩展和带符号扩展相关推荐

  1. matlab中的下划线怎么打,在matlab中怎么输入特殊符号~ , 怎么在Matlab中输入特殊符号...

    导航:网站首页 > 在matlab中怎么输入特殊符号~ , 怎么在Matlab中输入特殊符号 在matlab中怎么输入特殊符号~ , 怎么在Matlab中输入特殊符号 匿名网友: 一.文档中的T ...

  2. php 代码符号,网站开发编程中的特殊符号处理_php

    1 php中单引号与双引号的区别 在PHP中,通常一个字符串被定义在一对引号中,如: 'I am a string in single quotes' "I am a string in d ...

  3. matlab中特殊符号ommiga,在MATLAB中输入特殊符号---方法集锦

    在matlab中怎么输入特殊符号 Character Sequence Symbol Character Sequence Symbol Character Sequence Symbol \alph ...

  4. linux去掉文件中数值符号,去掉linux文本文件中的 ^M 符号

    在linux下,不可避免的会用VIM打开一些windows下编辑过的文本文件.我们会发现文件的每行结尾都会有一个^M符号,这是因为 DOS下的编辑器和Linux编辑器对文件行末的回车符处理不一致, 对 ...

  5. c语言弱符号与函数指针,浅谈C语言中的强符号、弱符号、强引用和弱引用【转】...

    首先我表示很悲剧,在看<程序员的自我修养--链接.装载与库>之前我竟不知道C有强符号.弱符号.强引用和弱引用.在看到3.5.5节弱符号和强符号时,我感觉有些困惑,所以写下此篇,希望能和同样 ...

  6. wpf中xaml的类型转换器与标记扩展

    wpf中xaml的类型转换器与标记扩展 原文:wpf中xaml的类型转换器与标记扩展 这篇来讲wpf控件属性的类型转换器 类型转换器 类型转换器在asp.net控件中已经有使用过了,由于wpf的界面是 ...

  7. class根据状态 vue_搞懂并学会运用 Vue 中的无状态组件

    啥是应用程序状态,为什么咱们需要它? 状态管理通常在较小的项目并不需要,但是当涉及到更大的范围时,如企业级的应用大部分需要它了.简单的说,状态是一个包含应用程序使用的最新值的对象.但是,如果咱们从结构 ...

  8. 平均的计算机符号,如何在Word中输入平均数的符号X上加一横(X拔)

    word是一款非常实用的办公软件,我们经常会使用word进行文档编辑,我们在使用中不可避免会遇到编辑数学公式,例如在Word中输入平均数的符号X上加一横(X拔), 那应该怎么编辑呢?接下来就跟着小编一 ...

  9. c语言中的无符号字节,C语言之有符号数和无符号数

    我们知道,在C语言中存在无符号数和有符号数(一些高级语言如Java里面是没有无符号数的),但是对于计算机而言,其本身并不区别有符号数和无符号数,因为在计算机里面都是0或者1,但是在我们的实际使用中有时 ...

  10. c语言无符号扩展,C语言无符号和有符号的区别

    C语言定义一个int类型时,默认是有符号数,关键字signed常省略,如: int a; signed int a; signed a; 这三句是一样的定义 定义无符号数时,必须加关键字unsigne ...

最新文章

  1. 【CV】Anaconda 安装教程|CSDN创作打卡
  2. bitmap文件格式分析
  3. Numpy.array矩阵百分制化(比例化)
  4. c# automapper 使用
  5. Adobe illustrator 介绍几个快捷键 - 连载 8
  6. 在高并发情况nginx的作用
  7. 查看mysql 表 被人删除_我的数据库中有一表总是被什么人删掉数据?我如何查出来是谁做的?...
  8. 软件工程第三次作业(最大子段和)
  9. matlab调用refprop完全说明,Matlab调用REFPROP终极版说明
  10. Ubuntu 安装 OpenCV(亲测有效)
  11. DHTMLX-Grid
  12. python之numpy之方差numpy.var
  13. ML语言/函数式编程原理(一)
  14. 【计算机图形学实验1——实现中点画线算法、Bresenham画线算法】
  15. 西安鹏程张建宁老师主讲网络安全
  16. 【笔记】H5跳转手机应用商店(指定应用页/第三方应用商店)
  17. PHP socket 连接 Socket server
  18. 一起打造自己的自动驾驶小车mycar - 4.手柄控制小车移动
  19. Vue2.5从零开发猫眼④——Home页开发
  20. 设计师必备的PPT辅助神器-iSlide

热门文章

  1. 服务端开发所需技能归纳
  2. 自己搭建了一个简单实用的Web版记事本
  3. 通过企业账号邀请开发者(不需要支付99刀,在真机上调试)
  4. myeclipse-10.7-offline-installer-windows安装图解及注意事项
  5. 浪人下载和浪人文章的漏洞利用
  6. 模式识别和机器学习--- 2.3高斯分布
  7. 孙鑫VC学习笔记:第十九讲 动态链接库
  8. 代写R语言assignment经常用到的代码语法分享!
  9. ERROR: Cannot uninstall ‘wrapt‘. It is a distutils installed project and thus we cannot accurately
  10. windows 和 ubuntu服务器之间用Xshell互传文件