C语言的补码表示和unsigned及signed的的转换

这东西实际编程时一直无视的,范围小了就换个大点的表示形式,但是总觉得基础知识还是掌握得好,免得到时候用移位运算或类型转换或笔试题时要花时间想。

C语言的基本类型有char、int、float、double,另外还有说明符long、short、signed和unsigned。

首先要注意在不同操作系统中类型大小不一样,下面的情况只是考虑其中一种情况。

int和char均默认为signed,二进制的最高一位来表示符号,0为正1为负。

假如short int是16位,由于第1位表示正负,所以只剩15位表示实际数值,范围为-2^15到2^15-1

举例,按照原码表示:

0000 0000 0000 0101表示5

1000 0000 0000 0101表示-5

反码就是符号位不变,数值位取反,比如5就表示为0111 1111 1111 1010

但是这样问题来了,1000 0000 0000 0000跟0000 0000 0000 0000表示的都是0,这样0就有2种编码方式。

所以C语言采取了补码表示,1000 0000 0000 0000表示的是-2^15而非0。

补码:1、对于正数,补码与原码相同;2、对于负数,数值位的绝对值取反后在最低位加1。

因此,C语言中是用表示-5的是1111 1111 1111 1011

那么对负整数逐次进行自加运算得到结果如下

-4  1111 1111 1111 1100

-3  1111 1111 1111 1101

-2  1111 1111 1111 1110

-1  1111 1111 1111 1111

于是-1再自加后所有位数全部变为0,0的表示形式就变成了0000 0000 0000 0000,表示0的只有一种形式。

char在计算机内部是用一个字节的二进制来表示的,这里假定默认为signed,表示范围为-128到127。

对于char c = 128; c的二进制表示为1000 0000,如果转换成int输出是-127。

char转换成short int并不是说位数增加了,而是把它当成short int来解释,因此c还是1000 0000,表示的是-127,而不会因为转型为int就变成了0000 0000 1000 0000

看下面一段代码,signed转unsigned

int _tmain(int argc, _TCHAR* argv[])
{
	char c = 128;
	unsigned char cu = c;
	short int i = cu;
	cout << i;
	return 0;
}

把c转换成unsigned char后,再转换成short int,那么输出的就是128,转型后还是1000 0000,但是按照unsigned的解释,最高位不再是符号位,而是数值位,所以结果就是2^8=128。

好了,再看下面一段代码,unsigned转signed

int _tmain(int argc, _TCHAR* argv[])
{
	unsigned char cu = 255;
	char c = cu;
	short int i = c;
	cout << i;
	return 0;
}

255的unsigned表示为 1111 1111,转换为signed后,符号位1代表是负数,数值位转换成十进制后是127,按照补码的定义结果为-1。

以前用OpenCV处理图像时,经常被绕住,因为IplImage*的ImageData是char表示的,而处理图像时一般都转化成了unsigned char,回顾了补码的概念后那么下面这个对应就好理解了。

数值区间 [0,127] [-128,-1]
char x x
unsigned char x 256+x
时间: 2024-10-29 19:07:50

C语言的补码表示和unsigned及signed的的转换的相关文章

unsigned与signed区别

我们来一起看下,C语言中,对于Integer Type(整数形式)的unsigned与signed两种形式的区别,以及在内存中的存储方式是如何的 Integer type(整数形式)是C语言中的基本数据形式之一,可以究竟对于Integer的定义是什么呢? 翻书看下,在介绍Integer的时候,还有一个关键词就是size(范围) The C Programming Language 写道 an integer,typically reflecting the natural size of int

unsigned 和 signed

http://www.cnblogs.com/stonehat/archive/2011/10/14/2212141.html http://m.blog.csdn.net/blog/u010086298/37777607 先看两个例子 #include <stdio.h> int main(int argc, char *argv[]) { unsigned char a = -1; char b = a; printf("%d %d",a,b); return 0; }

c语言中的unsigned 和 signed

我们来一起看下,C语言中,对于Integer Type(整数形式)的unsigned与signed两种形式的区别,以及在内存中的存储方式是如何的 Integer type(整数形式)是C语言中的基本数据形式之一,可以究竟对于Integer的定义是什么呢? 翻书看下,在介绍Integer的时候,还有一个关键词就是size(范围) The C Programming Language 写道 an integer,typically reflecting the natural size of int

mysql 中int类型字段unsigned和signed的探索

转自:http://www.0791quanquan.com/news_keji/topic_816453/ 探索一:正负数问题 拿tinyint字段来举例,unsigned后,字段的取值范围是0-255,而signed的范围是-128 - 127. 那么如果我们在明确不需要负值存在的情况下,通常是不要设置signed来支持负数的. 因为只支持正数会让存储空间大一倍呢(当然我这种表达可能不准确). 假设我们使用tinyint来存储一些状态值. 0表示删除,1表示待付款,2表示已付款,3....

[C知识点]char unsigned char signed char知识点

1.char,unsigned char, signed char 都是占一个字节. 2.signed char范围为 -128-127  0000 0000表示+0 1000 0000表示-0.+0和-0表示的值是一样的.为了不浪费这一位用1000 0000表示128 unsigned char范围为 0-256. 3. char根据编译器的不同,被解释成signed char或者unsigned char. 4.VC编译器.x86上的GCC都把char定义为signed char,而arm-

一段代码的疑问(1)——unsigned与signed

现象: 先来看一段代码: 这段代码的输出结果是: -84 4294967264 分析: [email protected]:~/cpp$ g++ -g c212.cc -o temp [email protected]:~/cpp$ ls c143.cc c144.cc c212.cc temp 可以看到多出一个temp文件 [email protected]:~/cpp$ gdb temp GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2

C语言char*字符串数组和unsigned char[]数组的相互转换

#include <iostream> #include <string> using namespace std; void convertUnCharToStr(char* str, unsigned char* UnChar, int ucLen) { int i = 0; for(i = 0; i < ucLen; i++) { //格式化输str,每unsigned char 转换字符占两位置%x写输%X写输 sprintf(str + i * 2, "%

C语言 —— 打印不同对象的字节表示 ( 对int*强制转换成unsigned char*的理解 )

此文章参考<深入理解计算机系统>P31. 先看如下代码:  12345的十六进制表示为:0x00003039 1 #include <stdio.h> 2 3 int main() 4 { 5 int a = 12345; 6 char *q = (char *)(&a); 7 for(int i = 0; i < sizeof(a); ++i) 8 printf("%.2x ", q[i]); 9 return 0; 10 } 输出为: a的地址

C语言下double转char*或者std::string,可以精确转换不含多余的0

char* GetDoubleStr(double value) { char buf[32]={0};//长度可以自定义 sprintf(buf,"%.8f",value);//保留8位小数,不够补0 int index = 0; int len = strlen(buf); for(int i = len-1;i>0;i--) { if(buf[i] == '0') continue; else { if(buf[i] == '.') index = i; else inde