有符号变量与无符号变量的值的转换

最近了解了一下有符号变量与无符号变量的区别和联系,看下面代码:

  1. #include <stdio.h>  
  2.   
  3. char getChar (int x,int y)  
  4. {  
  5.     char c;   
  6.     unsigned int a = x;  
  7.   
  8.     (a+y > 10) ? (c = 1): (c = 2);  
  9.   
  10.     return c;  
  11. }   
  12.   
  13. int main (void)  
  14. {  
  15.     char c1 = getChar(7,4);  
  16.     char c2 = getChar(7,-7);  
  17.     char c3 = getChar(7,-8);  
  18.     char c4 = getChar(-6,7);  
  19.       
  20.     printf("c1 = %d\n",c1);  
  21.     printf("c2 = %d\n",c2);  
  22.     printf("c3 = %d\n",c3);  
  23.     printf("c4 = %d\n",c4);  
  24.       
  25.     return 0;  
  26. }  

程序输出结果为:

c1 = 1;

c2 = 2;

c3 = 1;

c4 = 2;

首先说明getChar()函数的作用:将参数x的值转换为无符号整形后再与y相加。其结果与101进行比较,如果大于10则函数返回1,否则返回2。

注意:当表达式中存在有符号类型和无符号类型时,所有的操作数都自动转换为无符号型。

因此y值会首先自动转换成无符号的整数,然后和a相加,最后再与10进行比较。


以下是打印的各个值的分析:

c1:传入参数分别为7和4,两个数相加后为11,大于10,c1返回1;

c2:传入参数分别为7和-7,负数在转为无符号整数数时会先求出其补码,在32位的编译器中,-7的原码为1000 0000 0000 0000 0000 0000 0000 0111,

补码为1111 1111 1111 1111 1111 1111 1111 1001,7的补码为0000 0000 0000 0000 0000 0000 0000 0111,相加再转换为十进制为4294967296,而无符号整形的范围 为

0~4294967295,显然溢出了1,其最终值为0,0小于10,所以c2 = 2;

c3:传入参数分别为7和-8,同上,a+y = 4294967295 ,刚好达到无符号整型的极限,大于10,所以c3 = 1;

c4:传入参数分别为-6和7,同上,a+y = 4294967297,溢出2,其最终值为1,小于10,所以c3 = 2;


C语言中提供了很多整数类型(整型),主要区别在于它们取值范围的大小。int代表有符号的整数,也就是说,用int声明的变量可以是正数也可以是负数,也可以是零,但是只能是整数。
比如:int a = 3; int b = 0; int c = -5;
以上这些都是合法的。
int的取值范围因机器而异,一般而言,在较旧的PC上,int值在内存中一般是按2个字节(16位)进行存储的,在较新的PC以及工作站和大型机上,int值在内存中一般是按照4个字节(32位)进行存储的。


C语言中将基本数据类型划分为signed(有符号)和unsigned(无符号)两大类。
例如,初始化变量int a = -3;其实它等价于signed int a = -3;关键字signed在这里可以省略,因为C语言默认就是有符号类型的,如果要定义无符号类型的数(也就是0和正整数)可以这样定义,unsigned int b = 5;

为了说明清楚signed和unsigned的区别,首先需要了解数据在内存中是如何存储的,在计算机中所有的数据都是按照二进制进行存储的(以下假设在字长为2个字节的机器上来表示)。

举个例子来说,unsigned  int a = 1; 变量a在内存中就是以00000000 00000001来存储的,用图表的形式表示:



因为这里是unsigned  int,它是无符号整型,所以的它的16位全部用来表示数据。

int b = -1;

这里情况就稍微有点复杂了,注意数字1和-1在内存中的存储是完全不一样的,请看,

在计算机中,整数是以原码的形式存储的,而负数是以补码的形式存储的,原码大家都知道也就是它对应的二进制码,那什么是补码呢,就是原码的反码加1,反码就是原码的各位取反,例如-1的补码是:

首先1的原码是                     00000000 00000001

其次取它的反码是                 11111111 11111110

最后在其反码的基础上加上1   11111111 11111111

得到-1的补码是,11111111 11111111

用图表的形式表示:

http://hi.csdn.net/attachment/201008/11/0_1281514535se1Q.gif

从上图中可以看出,int用15位来表示一个数字,第1位被符号位占用了,其实大家应该不难看出在数学中-1是负数中最大的整数,所以这里看到它的各个位都置1,对应于二进制来讲就是最大的数了,计算机就是按照符号位来识别该数是正是负,所以第一位只起到标识的作用并不作为数据位来使用,而其余的15位才是真正的数据位。以补码的形式来存储有个好处那就是计算机将负数的运算当作加法来处理了。那么将一个有符号的数赋给一个无符号的数会发现一个很有趣的现象,比如:

unsigned int a;

int b = -1;

a = b;

printf("a=%u",a);

输出a=65535,这个结果是怎么出来的呢?其实很简单,b=-1,根据上图-1在计算机中的数据位是1111111 11111111,注意是数据位,是要去掉符号位的,所以是15位,a是无符号类型的整数,将b赋给a,自然a就是1111111 11111111,也是15位第一位补0,转换成十进制就是65535,它也是unsigned int范围的最大上限(0~65535 216-1),-1是最大的负整数转换成正整数当然也是最大了,这个应该很好理解了。

参考文章:http://bbs.csdn.net/topics/340253678

https://blog.csdn.net/BiuBiu741/article/details/75807953

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页