zoukankan      html  css  js  c++  java
  • C中signed与unsigned

    1 unsigned int i=3;
    2 cout<<i * -1;
    问结果是多少。

    第一反应:-3。不过结果似乎不是这样的,写了个程序,运行了一下,发现是:4294967293。

    1)在32位机上,int型和unsigned int型都是32位的(4个字节)。
    2)enum会跟据最大值来决定类型,一般来说为int型,如果超出int型所能表示的范围,则用比int型大的最小类型来表示(unsigned int, long 或者unsigned long)
    3)关于类型的大小。一般用所能表示的数据范围来比较类型的大小,如char型<unsigned char型<short型...在表达式中,一般都是由小的类型向大的类型转换(强制类型转换除外)
     
    下面结合自己查的资料,加上自己不断地举各种情况编程,总结一下关于类型转换(仅限于算术表达式中关于整数类型的转换)的一些问题(如有缺漏,欢迎补充,感激不尽)
    1、所有比int型小的数据类型(包括char,signed char,unsigned char,short,signed short,unsigned short)转换为int型。如果转换后的数据会超出int型所能表示的范围的话,则转换为unsigned int型;
    2、bool型转化为int型时,false转化为0,true转换为1;反过来所有的整数类型转化为bool时,0转化为false,其它非零值都转为true;
    3、如果表达式中混有unsigned short和int型时,如果int型数据可以表示所有的unsigned short型的话,则将unsigned short类型的数据转换为int型,否则,unsigned short类型及int型都转换为unsigned int类型。举个例子,在32位机上,int是32位,范围–2,147,483,648 to 2,147,483,647,unsigned short是16位,范围0 to 65,535,这样int型的足够表示unsigned short类型的数据,因此在混有这两者的运算中,unsigned short类型数据被转换为int型;
    4、unsigned int 与long类型的转换规律同3,在32位机上,unsigned int是32位,范围0 to 4,294,967,295,long是32位,范围–2,147,483,648 to 2,147,483,647,可见long类型不够表示所有的unsigned int型,因此在混有unsigned int及long的表达式中,两者都被转换为unsigned long;
    5、如果表达式中既有int 又有unsigned int,则所有的int数据都被转化为unsigned int类型。
     
    经过这番总结,前面提出的问题的答案应该就很明显了吧。在表达式i*-1中,i是unsigned int型,-1是int型(常量整数的类型同enum),按第5条可以知道-1必须转换为unsigned int型,即0xffffffff,十进制的4294967295,然后再与i相乘,即4294967295*3,如果不考虑溢出的话,结果是12884901885,十六进制0x2FFFFFFFD,由于unsigned int只能表示32位,因此结果是0xfffffffd,即4294967293。
     
    在C语言中,signed要求最高位是符号位,以下表示数据大小,而unsigned则全部位都表示大小。如果用8位二进制表示的话,signed范围就是-128到127,unsigned就是

    0到255,C语言中专门用两个关键字来描述两种表示方法,于是,就产生了一些不可思议的问题。

    1、溢出

      在有符号运算中可能会产生溢出问题,归纳起来就是:两个整数相加可能会溢出,两个负数相加也可能会溢出,一正一负相加肯定不会溢出。在《C深度剖析》中看到一个有趣的问题。

     1 #include <stdio.h>
     2 #include <string.h>
     3 int main(void)
     4 {
     5   char a[1000];
     6   int k = 0;
     7   for (; k < 1000; k++) 
     8     {
     9       a[i] = -1-i;  
    10 
    11   }
    12   printf("%d
    ", strlen(a));
    13   return 0;
    14 }

      最终的结果是255。因为数组a[1000]是char类型的,在C语言中明确规定char类型占一个字节内存空间,且在x86的gcc平台上 char默认是signed,一开始,k=0,a[0]=-1,随着k不断增大,当k=127,则a[127]=-128,对应的二进制是 10000000,我们知道-128是编译器能表示的最小值,当k=128,a[128]当然不可能存储-129这个值了,因为最高位发生了溢出,所以在 计算机中储存的补码值是01111111,。随着k继续增大,当k=254时,a[254]在计算机中存放的补码是00000001,而 k=255,a[255]对应的存储值是00000000,即0,strlen函数遇到第一个0就停止,所有最后的结果是k从0到254,总共长度是 255。

    2、signed和unsigned混合运算

      C语言中除了char类型,编译器默认其他整型都是signed,在x86的gcc平台上包括char在内所有整型都是signed。

     1 #include <stdio.h>
     2 
     3 int main(void)
     4 {
     5 unsigned a = 10;
     6 unsigned b = -10;
     7 if (a) printf("yes
    "); else printf("no
    ");
     8 if (b) printf("yes
    "); else printf("no
    ");
     9 
    10 int c = b;
    11 printf("%d
    ", c);
    12 if (c) printf("yes
    "); else printf("no
    ");
    13 
    14 int d = -20;
    15 int e = a + d;
    16 printf("%d
    ", e);
    17 if (e) printf("yes
    "); else printf("no
    ");
    18 
    19 return 0;
    20 }

    最后结果是

    yes
    yes
    -10
    yes
    -10
    yes

      从上面例子可以看出,在C语言中,有符号数可以赋值给无符号数,结果是一个无符号数,而无符号数也可以赋值给有符号数,结果还是一个无符号数;在混合运算中,只要有一个无符号数,都会将有符号数转化成无符号数参加运算,结果也以无符号保存。

    注意:signed 和 unsigned 在电脑中的存储形式是一样的,只是解释方法不同,即一个有符号,一个无符号。

    %d打印的是signed类型的,而%u才是打印的unsignd类型的,用不同的打印相当于一个类型转换了。当然C++比较直观,能直接自动识别出类型并打印值。

    就用上面的例子:

    unsigned c = 3;
    printf("%d
    ",(c*(-1)));       //  打印出的是-3    
    printf("%u
    ",(c*(-1)));       //  打印出的是4294967293
  • 相关阅读:
    非域环境下搭建自动故障转移镜像无法将 ALTER DATABASE 命令发送到远程服务器实例的解决办法
    AWS 免费套餐
    SQL Server全时区转换
    SQL Server 连接问题案例解析(1)
    SQL Saturday活动再起
    SqlServerProxy的一些资料
    数据是企业的无价財富——爱数备份存储柜server的初体验(图文)
    JEECG第二期深入使用培训(报名截止2014-06-21)
    Java提高篇(三三)-----Map总结
    经常使用哈希函数的比較及其C语言实现
  • 原文地址:https://www.cnblogs.com/balingybj/p/4686562.html
Copyright © 2011-2022 走看看