欢迎来到天天文库
浏览记录
ID:9000491
大小:15.15 KB
页数:3页
时间:2018-04-14
《关于有符号数、无符号数和数据类型的总结》由会员上传分享,免费在线阅读,更多相关内容在应用文档-天天文库。
1、一、 CPU只会根据输入信号进行逻辑运算,在硬件级别是没有有符号无符号的概念,运算结束会根据运算前的信号和输出信号来设置一些标志位,是不是有符号由写程序的人决定,标志位要看你把操作数当有符号还是无符号来选择,就像内存中的数据,你可以按照需要来解析,原始数据在那里,你要按什么数据格式来解析在于自己的选择,所以玩汇编的要做到心里有数,加减法只有一套指令,因为这一套指令同时适用于有符号和无符号。下面这些指令:muldivmovzx…是处理无符号数的,而这些:imulidivmovsx…是处理有符号的。举例来说:内存里有一个字节
2、x为:0xEC,一个字节y为:0x02。当把x,y当作有符号数来看时,x=-20,y=+2。当作无符号数看时,x=236,y=2。下面进行加运算,用add指令,得到的结果为:0xEE,那么这个0xEE当作有符号数就是:-18,无符号数就是238。所以,add一个指令可以适用有符号和无符号两种情况。(呵呵,其实为什么要补码啊,就是为了这个呗,:-))乘法运算就不行了,必须用两套指令,有符号的情况下用imul得到的结果是:0xFFD8就是-40。无符号的情况下用mul,得到:0x01D8就是472。二、C又是可怕的,因为它把
3、机器层面的所有的东西都反应了出来,像这个有没有符号的问题就是一例(java就不存在这个问题,因为它被设计成所有的整数都是有符号的)。为了说明c的可怕特举一例:#include#includeintmain(){ intx=2; char*str="abcd"; inty=(x-strlen(str))/2; printf("%d",y);}结果应该是-1但是却得到:2147483647。为什么?因为strlen的返回值
4、,类型是size_t,也就是unsignedint,与int混合计算时类型被自动转换了,结果自然出乎意料。。。观察编译后的代码,除法指令为div,意味无符号除法,即将-2看做无符号数了。解决办法就是强制转换,变成inty=(int)(x-strlen(str))/2;强制向有符号方向转换(编译器默认正好相反),这样一来,除法指令编译成idiv了。我们知道,就是同样状态的两个内存单位,用有符号处理指令imul,idiv等得到的结果,与用无符号处理指令mul,div等得到的结果,是截然不同的!所以牵扯到有符号无符号计算的问题
5、,特别是存在讨厌的自动转换时,要倍加小心!(这里自动转换时,无论gcc还是cl都不提示!!!)为了避免这些错误,建议,凡是在运算的时候,确保你的变量都是signed的。三、自动类型转化时的,短字节向长字节转化时,有符号数会符号扩展,无符号数会0扩展;长字节向短字节转化时,会自动截取高位,留下低位字节。特别在做算术运算时,比如乘除法,就可能涉及到有符号数自动转化为无符号数,从而采用不同的指令处理。例如:下面的代码输出是什么,为什么?voidfoo(void){unsignedinta=6;intb=-20;(a+b>6)?
6、puts(">6"):puts("<=6");} 这个问题测试你是否懂得C语言中的整数自动转换原则,我发现有些开发者懂得极少这些东西。不管如何,这无符号整型问题的答案是输出是”>6”。原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。因此-20变成了一个非常大的正整数,所以该表达式计算出的结果大于6。这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。如果你答错了这个问题,你也就到了得不到这份工作的边缘。扩展一下,如果是这段代码呢?voidfoo(void){unsigne
7、dinta=6;intb=-20;printf("%d",a+b);(a+b>6)?puts(">6"):puts("<=6");}结果是输出:-14 >6 为什么?我们要注意,在printf()中,a+b也是转换为unsignedint(0xF2)的,但是%d要求又是按照有符号数输出,所以0xf2当成有符号数输出了-14。四。特别注意在有常数的算数表达式中,往往有隐含的数据类型转化,因为整数常量并没有明确的被指出其的数据类型,整常数在不加特别说明时总是正值。如果需要的是负值,则负号“-”必须放置于常数表达式的前
8、面。每个常数依其值要给出一种类型。当整常数应用于一表达式时,或出现有负号时,常数类型自动执行相应的转换,十进制常数可等价于带符号的整型或长整型,这取决于所需的常数的尺寸。八进制和十六进制常数可对应整型、无符号整型、长整型或无符号长整型,具体类型也取决于常数的大小。如果常数可用整型表示,则使用整型。如果常数值大于一个整
此文档下载收益归作者所有