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

第一反应:-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[];
  6.   int k = ;
  7.   for (; k < ; k++)
  8. {
  9.    a[i] = --i;  
  10.  
  11.   }
  12.   printf("%d\n", strlen(a));
  13.   return ;
  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 = ;
  6. unsigned b = -;
  7. if (a) printf("yes\n"); else printf("no\n");
  8. if (b) printf("yes\n"); else printf("no\n");
  9.  
  10. int c = b;
  11. printf("%d\n", c);
  12. if (c) printf("yes\n"); else printf("no\n");
  13.  
  14. int d = -;
  15. int e = a + d;
  16. printf("%d\n", e);
  17. if (e) printf("yes\n"); else printf("no\n");
  18.  
  19. return ;
  20. }

最后结果是

yes
yes
-10
yes
-10
yes

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

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

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

就用上面的例子:

  1. unsigned c = ;
  2. printf("%d\n",(c*(-))); // 打印出的是-3
  3. printf("%u\n",(c*(-))); // 打印出的是4294967293

C中signed与unsigned的更多相关文章

  1. C语言中signed和unsigned理解

    一直在学java,今天开始研究ACM的算法题,需要用到C语言,发现好多知识点都不清楚了,看来以后要多多总结~ signed意思为有符号的,也就是第一个位代表正负,剩余的代表大小,例如:signed i ...

  2. Bit operator: Left shift and Right shift (Signed or unsigned? )

    No matter left shift or right shift, the result's sign should always be the same as its left operand ...

  3. is char signed or unsigned?

    工作这么多年,一直认为char是有符号的,而事实上gcc和vs默认也是有符号,但是c规范里实际并没有指明char是有符号还是无符号,所以char比较特殊, char signed char unsig ...

  4. C语言:signed和unsigned的区别

    参考博客:https://blog.csdn.net/wen381951203/article/details/79922220 signed和unsigned用于修饰整数类型(包括char,从ANS ...

  5. c++基础类型之signed、unsigned的一个细节

    数值型 c++中,对于 int.long.int64....等这些数值类型,如果是有符合的,则类型前加不加 signed 其效果都是一样的. 比如如下声明: int nA; // 与 signed i ...

  6. signed和unsigned

    signed:表示有符号位,最高位包括正数.负数和0: unsigned:表示无符号位,最高位表示 数值,不表示符号: signed int a:a 的取值范围是:-2^..... 这个就想不起来要占 ...

  7. 嵌入式中的 *(volatile unsigned int *)0x500 解释

    C语言中*(volatile unsigned int *)0x500的解释: 如下: (unsigned int *)0x500:将地址0x500强制转化为int型指针*(unsigned int ...

  8. 转:VC中WORD,DWORD,unsigned long,unsigned short的区别(转)

    typedef unsigned long       DWORD;typedef int                 BOOL;typedef unsigned char       BYTE; ...

  9. verilog中signed的使用

    1.在verilog中有时会用signed修饰符来修饰定义的数据,运算的时候也会用$signed()任务来强制转换数据,那么signed的修饰是为什么呢,是为了区分有符号数和无符号数的加法和乘法吗?其 ...

随机推荐

  1. 用UltraISO制作支持windows 7的U盘启动盘

    用UltraISO制作U盘启动盘,有人写过,我也看过,不过依照网上的那些文章,成功的并不多,经过几次试验,在不同的主板环境下成功概率高的方法应该如下:   1. UltraISO建议9.3以上 2. ...

  2. 【循序渐进学Python】10.模块和包

    1.导入模块 任何Python程序都可以作为模块导入,只要Python解释器能找到我们定义的模块所在位置即可,一般来讲,在一个模块被导入时,Python解释器会按照下面的步骤进行搜索: 在当前所在目录 ...

  3. 【jQuery基础学习】03 jQuery中的事件与动画

    关于jQuery中的事件 js与HTML之间的交互是通过用户和浏览器操作页面时引发的事件来处理的. jQuery增加并扩展了基本的事件处理机制,jQuery不仅提供了更加优雅的事件处理方法,而且极大地 ...

  4. javascript的 == 与 === 的区别

    1.对于基础类型,例如string,number ==和===是有区别的 1)不同类型间比较,==之比较“转化成同一类型后的值”看“值”是否相等,===如果类型不同,其结果就是不等 2)同类型比较,直 ...

  5. web技术人员-推荐书籍

    学习是技术人员成长的基础,本次分享20本技术方面的书籍,这些书不是每一本都是经典,但是每一本都有其特点.以下20本大部分本人都看过,因此推荐给大家.(本次推荐的20本只是一个参考,比如像Head Fi ...

  6. android studio :com.android.support:appcompat-v7:21.+ 报错

    android studio :com.android.support:appcompat-v7:21.+ 报错: 在project——>app——>build.gradle修改: app ...

  7. Java对象 json之间的转换(json-lib)

    在这里主要简单的介绍一下,如何使用json-lib这个工具包来完成Java对象(或集合)与json对象(或集合)之间的转换~ 1. Java对象转换成json(既创建json) 关键类:JSONObj ...

  8. jquery实现页面控件拖动效果js代码

    ;(function($) { var DragPanelId = "divContext"; var _idiffx = 0; var _idiffy = 0; var _Div ...

  9. 模拟Select-Options对象实现多项数据输入功能

       模拟Select-Options对象实现多项数据输入功能 Select-Options对象可以同时输入多项值并将所输入数据存入内表以供程序使用,不过Select-Options的功能有一定的局限 ...

  10. C#知识点总结【2】

    此文章只是 记录在C#当中一些我个人认为比较重要的知识点,对于有些基础实现或者用法并未说明: 继承 C#当中可以实现两种继承方式 1.实现继承:一个类派生于一个类,它拥有基类的所有成员字段和函数. 2 ...