ImageVerifierCode 换一换
格式:DOC , 页数:11 ,大小:93KB ,
资源ID:3550787      下载积分:20 文钱
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,省得不是一点点
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.wenke99.com/d-3550787.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: QQ登录   微博登录 

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(C数据类型转换及操作.doc)为本站会员(hw****26)主动上传,文客久久仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知文客久久(发送邮件至hr@wenke99.com或直接QQ联系客服),我们立即给予删除!

C数据类型转换及操作.doc

1、void foo(void)unsigned int a = 6;int b = -20;(a+b 6) puts(“ 6“) : puts(“6 ”。原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。因此-20变成了一个非常大的正整数,所以该表达式计算出的结果大于6。这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。如果你答错了这个问题,你也就到了得不到这份工作的边缘在汇编语言层面,声明变量的时候,没有 signed 和 unsignde 之分,汇编器统统,将你输入的整数字面量当作有符号数处理成补码存入到计算机中,只有这一个标准!汇编器不会区分有

2、符号还是无符号然后用两个标准来处理,它统统当作有符号的!并且统统汇编成补码!也就是说,db -20 汇编后为:EC ,而 db 236 汇编后也为 EC 。这里有一个小问题,思考深入的朋友会发现,db 是分配一个字节,那么一个字节能表示的有符号整数范围是:-128 +127 ,那么 db 236 超过了这一范围,怎么可以?是的,+236 的补码的确超出了一个字节的表示范围,那么拿两个字节(当然更多的字节更好了)是可以装下的,应为:00 EC,也就是说 +236的补码应该是00 EC,一个字节装不下,但是,别忘了“截断”这个概念,就是说最后汇编的结果被截断了,00 EC 是两个字节,被截断成 E

3、C ,所以,这是个“ 美丽的错误”,为什么这么说?因为,当你把 236 当作无符号数时,它汇编后的结果正好也是 EC ,这下皆大欢喜了,虽然汇编器只用一个标准来处理,但是借用了“截断” 这个美丽的错误后,得到的结果是符合两个标准的!也就是说,给你一个字节,你想输入有符号的数,比如 -20 那么汇编后的结果是符合有符号数的;如果你输入 236 那么你肯定当作无符号数来处理了(因为236不在一个字节能表示的有符号数的范围内啊) ,得到的结果是符合无符号数的。于是给大家一个错觉:汇编器有两套标准,会区分有符号和无符号,然后分别汇编。其实,你们被骗了。:-)3.第一点说明汇编器只用一个方法把整数字面量

4、汇编成真正的机器数。但并不是说计算机不区分有符号数和无符号数,相反,计算机对有符号和无符号数区分的十分清晰,因为计算机进行某些同样功能的处理时有两套指令作为后备,这就是分别为有符号和无符号数准备的。但是,这里要强调一点,一个数到底是有符号数还是无符号数,计算机并不知道,这是由你来决定的,当你认为你要处理的数是有符号的,那么你就用那一套处理有符号数的指令,当你认为你要处理的数是无符号的,那就用处理无符号数的那一套指令。加减法只有一套指令,因为这一套指令同时适用于有符号和无符号。下面这些指令:mul div movzx 是处理无符号数的,而这些:imul idiv movsx 是处理有符号的。举例

5、来说:内存里有 一个字节 x 为: 0x EC ,一个字节 y 为:0x 02 。当把x,y当作有符号数来看时,x = -20 ,y = +2 。当作无符号数看时,x = 236 ,y = 2 。下面进行加运算,用 add 指令,得到的结果为:0x EE ,那么这个 0x EE 当作有符号数就是:-18 ,无符号数就是 238 。所以,add 一个指令可以适用有符号和无符号两种情况。 (呵呵,其实为什么要补码啊,就是为了这个呗,:-))乘法运算就不行了,必须用两套指令,有符号的情况下用imul 得到的结果是:0x FF D8 就是 -40 。无符号的情况下用 mul ,得到: 0x 01 D8

6、 就是 472 。4.为什么又扯到 c 了?因为大多数遇到有符号还是无符号问题的朋友,都是c里面的 signed 和 unsigned 声明引起的,那为什么开头是从汇编讲起呢?因为我们现在用的c 编译器,无论 gcc 也好,vc6 的cl 也好,都是将c语言代码编译成汇编语言代码,然后再用汇编器汇编成机器码的。搞清楚了汇编,就相当于从根本上明白了c ,而且,用机器的思维去考虑问题,必须用汇编。 (我一般遇到什么奇怪的c 语言的问题都是把它编译成汇编来看。 )C 是可爱的,因为c符合kiss 原则,对机器的抽象程度刚刚好,让我们即提高了思维层面(比汇编的机器层面人性化多了) ,又不至于离机器太远

7、(像c# ,java之类就太远了) 。当初Kchar * str = “abcd“;int y = (x - strlen(str) ) / 2;printf(“%dn“,y);结果应该是 -1 但是却得到:2147483647 。为什么? 因为strlen的返回值,类型是size_t ,也就是 unsigned int ,与 int 混合计算时有符号类型被自动转换成了无符号类型,结果自然出乎意料。 。 。观察编译后的代码,除法指令为 div ,意味无符号除法。解决办法就是强制转换,变成 int y = (int)(x - strlen(str) ) / 2; 强制向有符号方向转换(编译器默认

8、正好相反) ,这样一来,除法指令编译成 idiv 了。我们知道,就是同样状态的两个内存单位,用有符号处理指令 imul ,idiv 等得到的结果,与用无符号处理指令mul,div等得到的结果,是截然不同的!所以牵扯到有符号无符号计算的问题,特别是存在讨厌的自动转换时,要倍加小心为了避免这些错误,建议,凡是在运算的时候,确保你的变量都是 signed 的。定义 INT16S ltr1 = 0; ltr1 +;if(ltr1 = = 32767)ltr1 += 1;ltr1 += 2;当ltr1 等于32767时,到了有符号整数的最大值,加1就是-32768(0X8000)再加2就是-32766(

9、0X8002)6. INT16U i;INT16S *k;INT32S mbx;k = pmes + 7;mbx=0;for(i=0;iCOUNTOFCALSAMP;i+) /*32*4计算的周波 */mbx += *k;k +=NUMOFCAL; /*存放的是8个量*/ltr = labs(mbx); /整型量的值有可能出现负值时,当需要提取负值时需要用 labs取绝对值来反映其实际大小。ltr = (INT16U)(mbx); /整型量的值有可能出现负值时,当mbx = - 6时,即mbx = 0xfffffffa,这种强制转换并不能得到我们想要的值,相反它的结果很大,是fffa。7. I

10、NT16S ltr1;INT16U ltr2,ltr3;INT8U a;INT16S b;a= 6;b = -20;ltr1 = a + b;ltr2 = (INT16S)(a + b); c = 5;d = 15;ltr3 = c - d; /这个值会得到5到15之间的距离。结果是:ltr1 = -14 ltr2 = 65522 ltr3 = 65526当一个整型变量赋值给一个无符号的整型时,数据格式不变,直接复制。ltr1 本身是整型,ltr1 = a + b = 0xfff2 = - 14;Ltr2 本身是无符号整型,ltr2 = (INT16S)(a + b) 0xfff2 =6552

11、2 ;可见它们的16进制数值是一样的,这取决于赋值号左边的数据类型,这个法则只适合加减运算。Ltr3 当它是无符号整型时,值为 65526(0xfff6) ,当它为整型时,值为-10(0xfff6) ;其16进制表示是一致的,区别是要看赋值号左边的数据类型。这个法则只适合加减运算总结:1.当运算符两边一个是有符号整型,一个是无符号整型时,有符号整型转成无符号整型 ,然后再运算。这样问题就来了,当运算结果赋值给整型时是没有问题的,当运算结果赋值给无符号整型时,问题就有了,结果为负值的时候将得到一个很大数值,这个值用于运算时会出错。可见,整型量与无符号整型在16进制的写法上没有什么区别,当整型量的

12、负数部分从b1111 1111 1111 1111表示-1,b1000 0000 0000 0000表示-32768,这样的好处是便于加减法运算,可以将减法运算转变为加法运算,如 7 - 3 = 4,将3变为补码为:b1111111111111101 + b111 = b100;可见这是一种技法。8. INT8U a;INT16S b;INT16S ltr1;INT16S ltr1;INT16S acqbuf256;b = -12368;a = acqbuf222; ltr1 = b/a; Ltr2 = b/a;当acqbuf222 = 30 时,ltr1 = 1772,ltr2 = 1772

13、而不是我们要得到的负值。因为变量a是无符号整型,变量b的补码形式0xcfb0,运算时编译器将变量b当作无符号整型来运算,将最高位认为是数据,而不是符号,使用I$UDIV函数来运算,即0xcfb0 / 30 = 1772如果这样写ltr1 = b/acqbuf222 = -412;就对了,因为他们都是整型量,编译器使用I$DIV 函数来运算,将最高位认为是符号位。INT16U ltr1;INT16S ltr2; INT16S b;INT16S acqbuf256;b = -6;ltr1 = -6; /ltr1是无符号整型 所有ltr1 = 65530ltr2 = acqbuf224/b; /都为

14、整型,且负数除以负数等于正数,所有ltr2 = 1。10 INT16S ltr1;INT16S ltr2;INT8U a,c,d;INT16S b;INT16S acqbuf256;a = 635;b = -635;ltr1 = b/acqbuf222; /acqbuf222 = 29时,ltr1 = -21。ltr2 = a/acqbuf224; /acqbuf224 = -6时,ltr2 = 0。11. INT16S ltr1;INT16S ltr2;INT16U ltr3;INT16S acqbuf256;ltr1 = acqbuf222/-2; /acqbuf222 = 30时,ltr

15、1 = -15。ltr2 = acqbuf224/2; /acqbuf224 = -7时,ltr2 = -3。ltr3 = acqbuf224/2; /acqbuf224 = -7时,ltr2 = 0xfffd = 65533。以上除法编译的汇编语言中调用有符号的除法指令,I$DIV函数。再次总结:混合运算时,加减乘除的表达式中,运算符两边一个是有符号整型,一个是无符号整型时,有符号整型转成无符号整型 ,然后再运算。二进制运算以补码形式进行,不管加减乘除都会转化为这个形式,补码的好处就是将减法运算变为加法运算,这样的好处是可以省去硬件的减法电路。这样就出现了以下情况:在加减法运算时,处理器不区

16、分变量是有符号的还是无符号的,全部以补码方式运算。处理器的除法提供两种运算指令,一个是有符号的I$DIV,一个是无符号的I$UDIV,混合运算时就要慎重了,最好统一所有参与运算的变量,且都为有符号的整型变量,以免因转化带来不预期的运算结果。那么乘法呢,来看一个有意思的问题INT8U a;INT16S b;INT16S acqbuf256;INT16S ltr1;INT16S ltr2;b = -123;a = acqbuf222;ltr1 = b*a;/ ltr2 = b*acqbuf222;这里的ltr1= -3690 ,ltr2 = -3690。先解析ltr1的值,整型变量b = -123

17、 ,补码为 0xff85,由于变量a是无符号的,b*a在运算时将变量 b转化为无符号数 0xff85,将认为最高位为数据位。如果a = acqbuf222 = 30 ,乘法可以转变为加法运算,即30个 0xff85相加,相加结果产生溢出,截取16位值为0xF196 ,这个值就有意思了,当看着是整型量时,它等于 -3690;当看着是无符号的整型量时,它等于61846。ltr2 = b*acqbuf222;由于都是整型量,运算时乘法转变为加法运算,即30个 0xff85相加,相加结果产生溢出,截取16位值为0xF196 ,在结果上这两种算法没有区别。有了上面的分析,现在来重新看除法运算,在TMS3

18、20LF24系列的DSP 中,除法运算能不能用以下的方式来理解呢?INT16S a,c;INT16U b,f;INT16S acqbuf256;INT16S ltr1;INT16S ltr2;a = -123;b = acqbuf222;ltr1 = a/b;f = 123;c = acqbuf224;ltr2 = f/c;这里的ltr1= 2180 ,ltr2 = 0。运算发生符号转换,编译器使用 I$UDIV除法函数。先解析ltr1的值,整型变量a = -123,补码为 0xff85,由于变量b 是无符号的,a/b在运算时将变量a 转化为无符号数0xff85 ,将认为最高位为数据位。如果b

19、 = acqbuf222 = 30 ,除法可以转变为减法运算(补码算法还是加法) ,使用I$UDIV除法函数。 a/b = 0xff85/30是不是可以这样解释 ,I$UDIV除法可以转变为减法运算(补码算法还是加法) ,a/b转化为0xff85-30 = = 0xff85+0xFFE2,如果每次将加法运算的结果赋值给变量a,那么每加法运算一次,a 值减小一次,加2180次后f值将接近负数,由于是无符号除法运算,运算结果没有符号,2180就是a/b的结果。ltr2 =f/c;整型变量c = acqbuf224 = -6;补码为 0xfffa,123/0xfffa = 0。现在改一个变量类型,把

20、INT16U b,f;改为INT16S b,f;INT16S a,c;INT16S b,f;INT16S acqbuf256;INT16S ltr1;INT16S ltr2;a = -123;b = acqbuf222;ltr1 = a/b;f = 123;c = acqbuf224;ltr2 = f/c;这里的ltr1= -4 ,ltr2 = -20。运算没有发生符号转换,编译器使用I$DIV 除法函数。先解析ltr1的值,整型变量a = -123,补码为 0xff85,由于变量b 也是整型,如果b = acqbuf222 = 30 ,除法可以转变为减法运算(补码算法还是加法) ,使用I$D

21、IV除法函数。 a/b = 0xff85/30是不是可以这样解释,I$DIV除法可以转变为减法运算(补码算法还是加法) ,a/b转化为0xff85 + 30,如果每次将加法运算的结果赋值给变量a ,那么每加法运算一次, a值增加一次,加 4次后f值将接近正数,带上负号,那么-4就是a/b的结果。ltr2 =f/c;如果整型变量c = acqbuf224 = -6;补码为 0xfffa,除法可以转变为减法运算(补码算法还是加法) ,使用I$DIV除法函数。 f/c = 123/0xfffa 是不是可以这样解释,I$DIV 除法可以转变为减法运算(补码算法还是加法) ,那么f/c转化为 123 +

22、 0xfffa ,如果每次将加法运算的结果赋值给变量f,考虑正常溢出的话,每加运算一次,f值减小一次,加20次后f值将接近负数,那么带上负号-20就是 f/c的结果。附录:1计算机对有符号整数的表示只采取一套编码方式,不存在正数用原码,负数用补码这用两套编码之说,大多数计算机内部的有符号整数都是用补码,就是说无论正负,这个计算机内部只用补码来编码!只不过正数和0的补码跟他原码在形式上相同,负数的补码在形式上与其绝对值的原码取反加一相同。2-4有符号数的转换从到方法charshort符号位扩展charlong符号位扩展charunsigned char最高位失去符号位意义,变为数据位charun

23、signed short符号位扩展到short;然后从short 转到 unsigned shortcharunsigned long符号位扩展到long; 然后从long 转到unsigned longcharfloat符号位扩展到long; 然后从long 转到floatchardouble符号位扩展到long; 然后从long 转到doublecharlong double符号位扩展到long; 然后从long 转到long doubleshortchar保留低位字节shortlong符号位扩展shortunsigned char保留低位字节shortunsigned short最高位失

24、去符号位意义,变为数据位shortunsigned long符号位扩展到long; 然后从long转到unsigned doubleshortfloat符号位扩展到long; 然后从long 转到floatshortdouble符号位扩展到long; 然后从long 转到doubleshortlong double符号位扩展到long; 然后从long 转到doublelongchar保留低位字节longshort保留低位字节longunsigned char保留低位字节longunsigned short保留低位字节longunsigned long最高位失去符号位意义,变为数据位longFloat使用单精度浮点数表示。可能丢失精度。longdouble使用双精度浮点数表示。可能丢失精度。longlong double使用双精度浮点数表示。可能丢失精度。2-5无符号数的转换 从 到 方法unsigned char char 最高位作为符号位unsigned char short 0扩展unsigned char long 0扩展unsigned charunsigned short0扩展

Copyright © 2018-2021 Wenke99.com All rights reserved

工信部备案号浙ICP备20026746号-2  

公安局备案号:浙公网安备33038302330469号

本站为C2C交文档易平台,即用户上传的文档直接卖给下载用户,本站只是网络服务中间平台,所有原创文档下载所得归上传人所有,若您发现上传作品侵犯了您的权利,请立刻联系网站客服并提供证据,平台将在3个工作日内予以改正。