有(无)符号char型及其溢出问题
转载自:http://blog.sina.com.cn/s/blog_70ec9a6f01014j1h.html
1、char的有无符号类型
char 分为有符号性(signed)和无符号型(unsigned)两种:
Ø 若是signed型,就意味着取值范围为[-128,127];
Ø 若是unsigned型,就意味着取值范围为[0,255];
C语言中我们通常直接用类型char,但是它究竟是被当做signed型还是unsigned型,由编译器决定。
C语言允许我们在char前面加上关键字signed或者unsigned,这样,无论在编译器中被当做signed还是unsigned,都会按照前面加的这个关键字来决定。
例如:假设我们现在使用的编译器,把char当做signed来看到,则
char c1;
signed c2;
unsigned c3;
则c1和c2的取值范围都是[-128,127],而c3的取值范围则是[0,255]。
所谓取值范围,是指其值在这个范围之内时,会被正确处理,超出这个范围就会发生溢出。但在这个范围之内,并不意味着它就是可打印字符。这点不要混淆。
2、溢出
1)有符号
c1和c2一样,我们以c1为例来说明。先看向上超过上界的情况:
|
十进制 |
十六进制 |
二进制 |
值 |
|
126 |
0000007e |
0…0 0111 1110 |
126 |
|
127 |
0000007f |
0…0 0111 1111 |
127 |
|
128 |
ffffff80 |
1…1 1000 0000 |
-128 |
|
129 |
ffffff81 |
1…1 1000 0001 |
-127 |
|
130 |
ffffff82 |
1…1 1000 0010 |
-126 |
注:0…0表示24个0,1…1表示24个1
|
十进制 |
十六进制 |
二进制 |
值 |
|
-127 |
ffffff81 |
1…1 1000 0001 |
127 |
|
-128 |
ffffff80 |
1…1 1000 0000 |
-128 |
|
-129 |
0000007f |
0…0 0111 1111 |
127 |
|
-130 |
0000007e |
0…0 0111 1110 |
126 |
|
-131 |
0000007d |
0…0 0111 1101 |
125 |
|
-256 |
00000000 |
0…0 0000 0000 |
0 |
|
-257 |
ffffffff |
1…1 1111 1111 |
-1 |
从这两个表中可以看到,不管是否超过上下届也,不管是负数还是正数,每增加(减少)一个单位,就直接在二进制表示的最后一位上加(减)1。
相加或相减时,都可以先不看前24位:如果倒数第8位变为1,则前面24位全部设置为1,该数被解释为负数;如果倒数第8位变为0,则前面24位全部设置为0,该数被解释为正数。下面我们挑几个例子详细说明:
c1=128;
这时,会在127的最后8位上加1,原来的8位是0111 1111,加1后,变为1000 0000,于是把前面24个位也全部变为1,且该数被表示为负数。其值为-1*2^7+0=-128.
c1=129;
128的最后8位是1000 0000,加上后为1000 0001,前面24位保持1不变。该数被解释为负数,其值为-1*2^7+1=-127.
c1=-129;
-128的最后8位是1000 0000,减去1变为0111 1111,前面24位全部置位0,且该数被解释为正数,其值为2^0+2^1+2^2+2^3+2^4+2^5+2^6=2^7-1=127
c1=-130;
-127的最后8位是0111 1111,减去1变为0111 1110,前面24位全部保持0,且该数被解释为正数,其值为2^1+2^2+2^3+2^4+2^5+2^61=126
c1=-257;
由前面可以类推, -256的最后8位编码是0000 0000,减去1后变为1111 1111,前面24为全部置为1,该数被解释为负数,值为-1*2^7+2^0+2^1+2^2+2^3+2^4+2^5+2^6=-1。
注意:0000 0000减去1,也就是减去0000 0001,单看这8位的话,前面的数较小,我们可以想象在前面那个数的前面再加一个1,变成0001 0000 0000,后面那个数前面加0,变成0000 0000 0000,相减后,我们只看最后8位即可。
2)无符号
我们以c3为例进行说明。
|
十进制 |
十六进制 |
二进制 |
值 |
|
254 |
000000fe |
0…0 1111 1110 |
254 |
|
255 |
000000ff |
0…0 1111 1111 |
255 |
|
256 |
00000000 |
0…0 0000 0000 |
0 |
|
257 |
00000001 |
0…0 0000 0001 |
1 |
|
258 |
00000002 |
0…0 0000 0010 |
2 |
|
十进制 |
十六进制 |
二进制 |
值 |
|
-2 |
0000007e |
0…0 1111 1110 |
254 |
|
-1 |
0000007f |
0…0 1111 1111 |
255 |
|
0 |
ffffff80 |
0…0 0000 0000 |
0 |
|
1 |
ffffff81 |
0…0 0000 0001 |
1 |
|
2 |
ffffff82 |
0…0 0000 0010 |
2 |
其实和有符号型基本相同,唯一的差别就是,前面24位一直都置位0,且该数永远被解释为整数。下面举例说明:
c3=256;
因为255的最后8位是1111 1111,加1后变为0000 0000,所以其值为0;
c3=-1;
因为0的最后8位是0000 0000,减1后变为1111 1111,所以其值为255;
0000 0000减1,相当于减去0000 0001,虽然0的全码是0…0 0000 0000,似乎往上也没法借位,但是我们仍可将0000 0000前面一位加上1,看做0001 0000 0000减去0000 0000 0001,最后得到0000 1111 1111,我们直接去最后8为即可。
归纳:不管是有符号还是无符号,在前面的数小于后面的数时,都可假设在前面的数的上一位加1,而后面的数前面加0,从而进行相减;
另外,相加时,如果最高位,即倒数第8位变为0,只需直接将其变为0即可,其它位不变,不需要进位。
对于无符号型,前24位永远为0,对于有符号型,前24位永远和倒数第8位一样。
有(无)符号char型及其溢出问题的更多相关文章
- C语言之将无符号字符型转化为ascii码值
这个宏是在linux内核中获取的,主要的功能是能够将一个无符号字符型的参数转化为ASCII码值. ASCII : ASCII 编码里包括了128个字符.用 十进制 0 到 127 来表示 .那就对了 ...
- 整型,长整型,无符号整型等 大端和小端(Big endian and Little endian)
一.大端和小端的问题 对于整型.长整型.无符号整型等数据类型,Big endian 认为第一个字节是最高位字节(按照从低地址到高地址的顺序存放数据的高位字节到低位字节):而 Little endian ...
- 无符号整型 unsigned int、unsigned long、usigned long long、size_t 比较和格式控制
位数比较 由于数据的长度和平台相关,所以基于 64 位系统比较. Windows Linux unsigned int 32 bits/4294967295 32 bits unsigned long ...
- c语言int型和char型的自动类型转换
; //机器码为0xff unsigned ; //机器码0xfe if (a <= b){ printf("a <= b\n"); } else{ printf(&q ...
- CoreSeek有符号整型
数据库status字段的值有:-1,0,1 设置过滤字段,发现sql_attr_uint不支持负数,后改用sql_attr_bigint sql_attr_bigint = status sql_at ...
- C语言警告:warning C4018: “<”: 有符号/无符号不匹配
问题如下: 代码出问题之处: 原因分析: strlen返回一个无符号整型,也就是unsigned型,比较时应该两边的数据类型相同,故严格上来说,应该将m定义为unsigned型. 修改 ...
- C机器级移位,编码表示 无符号编码表示,有符号编码表示一般最常见的方式是补码
C机器级移位,编码表示 无符号编码表示,有符号编码表示一般最常见的方式是补码 w位补码所能表示的值范围是 首先我们得心知 补码的最高有效位是符号位,当符号位位1是表示的是负值,当符号位是0是,表示的 ...
- JavaScript 32位整型无符号操作
在 JavaScript 中,所有整数字变量默认都是有符号整数,这意味着什么呢? 有符号整数使用 31 位表示整数的数值,用第 32 位表示整数的符号,0 表示正数,1 表示负数. 数值范围从 -2^ ...
- 【VHDL】深度讲解二进制无符号和有符号加法处理溢出的问题
1.Unsigned adders 这个比较简单,只需在A.B前面扩展一位0防止溢出,溢出的数填到第n位cout,n-1到0位就是sum. , 2.Signed adders 一开始也搞不懂下图中为什 ...
随机推荐
- Live555研究之二Sleep实现
Live555通过一个while循环来不断读取socket,判断是否有连接进来,但是Live555并没有使用Sleep函数来让线程休眠多少毫秒来降低CPU占用率.Live555是通过select函数来 ...
- android 实现模拟按键
android 实现模拟按键方法一 通过Runtime实现,代码如下: try { String keyCommand = "input keyevent " + KeyEvent ...
- 【原创】使用Nmon_Analyzer处理较大nmon文件的方法
1 编写目的 进行性能测试时,测试服务器使用的操作系统是Linux或Unix时,我们一般会使用Nmon工具进行操作系统资源监控数据的收集.Nmon工具是一款非常优秀的性能监控和分析工具,它能够实时地收 ...
- 问题-WIN7 ..\Bin\InitCC32.exe".进程无法访问(拒绝访问)
问题现象: 问题原因:是InitCC32.exe没有权限. 问题处理:在DELPHI7的安装目录里设置用户权限,加入EVE... 这个用户.
- 转载 SharePoint【Site Definition 系列】– 创建Content Type
转载原地址: http://www.cnblogs.com/wsdj-ITtech/archive/2012/09/01/2470274.html Sharepoint本身就是一个丰富的大容器,里面 ...
- shell 检测ip的合法性与检测网络掩码的合法性
有时我们需要检测IP输入的正确性与网络掩码的正确性,用shell脚本写的: #验证ip地址的正确性 check_ip_format() { echo $1 | grep "^[0-9]\{1 ...
- 【Stage3D学习笔记续】山寨Starling(十一):Touch事件体系
我们的山寨Starling版本将会在这里停止更新了,主要还是由于时间比较有限,而且我们的山寨版本也很好的完成了他的任务“了解Starling的核心渲染”,接下来的Starling解析我们将会直接阅读S ...
- C++ vector的用法
其实我是一个比较懒惰的人 我最喜欢的循环方式是for(int i=0;i<length;i++) 同样也可以 for (unsigned i=0; i<sz; i++) myvector[ ...
- 剑指OFFER之从二叉搜索树的后序遍历序列(九度OJ1367)
题目描述: 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则输出Yes,否则输出No.假设输入的数组的任意两个数字都互不相同. 输入: 每个测试案例包括2行: 第一行为1个整数 ...
- 封装的多功能多效果的RecyclerView
开源界有一句很有名的话叫"不要重复发明轮子",当然,我今天的观点不是要反驳这句话,轮子理论给我们的开发带来了极大的便利,.但我想说的是,既要会用轮子,也要知道轮子怎么造,必要的时候 ...