(C语言)signed和unsigned类型转化
2011-08-07 22:40
411 查看
对于long, int, short, char等数据类型,我们可以通过signed和unsigned修饰来确定其能存储的数据范围。其中signed中保存的数据是可正可负,而unsigned的数据范围是0-对应数据类型的上限。
平时我们声明:int a的时候,默认a是一个signed类型的,也就是a可能是正值也可以是负值。
而在使用诸如printf函数的输出的时候,也需要注意输出的控制字符,即便声明的时候为:unsigned int a, 但是如果用printf("%d", a);进行输出,那么C语言在编译的时候会有一个隐性的转换,从而等同于:printf("%d", (signed)a);的结果。所以要输出一个unsigned int的值,需要使用printf("%u", a);的方式。
实际上无论是signed还是unsigned的方式,对于数据的二进制本身都是没有任何影响的,只是处理不同而已。比如:一个数据如果在内存中的二进制编码为:1001 0101,那么当使用signed进行解析的时候,高位的1,即:【1】001 0101,被看成了符号位。而当使用unsigned进行解析的时候高位的1和其他位上的1没有任何区别,都是用于存储数据的。在使用补码存储负数的情况下:
signed 1001 0101 = -107;
unsigned 1001 0101 = 149。
另外一个signed与unsigned在补足高位的时候也有一个显著的区别:
1、如果是一个signed的数据类型,那么在高位会按照符号位来进行补足,比如:1001 0101如果保存在两个字节中,那么结果是:1111 1111 1001 0101;
2、如果是一个unsigned的数据类型,那么在高位将直接补0,比如:1001 0101如果保留在两个字节中,那么结果是:0000 0000 1001 0101。
不同的补足方式,如果在后续的操作中将signed和unsigned进行转化,显示的结果也许会和你预想的大相径庭。
最后再补充一点,在数据进行signed和unsigned的转换时,默认是转化为int类型,而非你定义的类型,如:
short s = 10;
printf("%u", (unsigned) s); //这句话等价与:printf("%u", (unsigned int)s); 这就会导致前面提到的高位补数的问题,从而显示结果也许与预想不同。
所以如果你对数据占几个字节很了解,那么为了防止高位部位从而可能带来不必要的问题,还是进行显式的转换:
printf("%u", (unsigned short) s);
当然正如会出现高位补数的情况,也可能因为存储空间的减少而出现截断的现象,如:
printf("%u", (unsigned char) s); //short 一般占2个字节,而char仅仅占一个字节,这个时候s中的高位8位将丢失,仅仅保留低位的8位。
以下是以上叙述的一个段综合性代码:
环境:
1、Windows Home Ed SP3;
2、 Visual Studio C++ 6.0 Enterprise Ed。
4000
平时我们声明:int a的时候,默认a是一个signed类型的,也就是a可能是正值也可以是负值。
而在使用诸如printf函数的输出的时候,也需要注意输出的控制字符,即便声明的时候为:unsigned int a, 但是如果用printf("%d", a);进行输出,那么C语言在编译的时候会有一个隐性的转换,从而等同于:printf("%d", (signed)a);的结果。所以要输出一个unsigned int的值,需要使用printf("%u", a);的方式。
实际上无论是signed还是unsigned的方式,对于数据的二进制本身都是没有任何影响的,只是处理不同而已。比如:一个数据如果在内存中的二进制编码为:1001 0101,那么当使用signed进行解析的时候,高位的1,即:【1】001 0101,被看成了符号位。而当使用unsigned进行解析的时候高位的1和其他位上的1没有任何区别,都是用于存储数据的。在使用补码存储负数的情况下:
signed 1001 0101 = -107;
unsigned 1001 0101 = 149。
另外一个signed与unsigned在补足高位的时候也有一个显著的区别:
1、如果是一个signed的数据类型,那么在高位会按照符号位来进行补足,比如:1001 0101如果保存在两个字节中,那么结果是:1111 1111 1001 0101;
2、如果是一个unsigned的数据类型,那么在高位将直接补0,比如:1001 0101如果保留在两个字节中,那么结果是:0000 0000 1001 0101。
不同的补足方式,如果在后续的操作中将signed和unsigned进行转化,显示的结果也许会和你预想的大相径庭。
最后再补充一点,在数据进行signed和unsigned的转换时,默认是转化为int类型,而非你定义的类型,如:
short s = 10;
printf("%u", (unsigned) s); //这句话等价与:printf("%u", (unsigned int)s); 这就会导致前面提到的高位补数的问题,从而显示结果也许与预想不同。
所以如果你对数据占几个字节很了解,那么为了防止高位部位从而可能带来不必要的问题,还是进行显式的转换:
printf("%u", (unsigned short) s);
当然正如会出现高位补数的情况,也可能因为存储空间的减少而出现截断的现象,如:
printf("%u", (unsigned char) s); //short 一般占2个字节,而char仅仅占一个字节,这个时候s中的高位8位将丢失,仅仅保留低位的8位。
以下是以上叙述的一个段综合性代码:
环境:
1、Windows Home Ed SP3;
2、 Visual Studio C++ 6.0 Enterprise Ed。
/* Date: 2011-08-03 Author: garyHost; Description: 查看使用(unsigned char)ch 方式以及 (unsigned)ch的区别; Remarks: 1) */ #include <stdio.h> #include <stdlib.h> #include "myTools.h" #define _STRING_END_FLAG '\0' //字符串休止符号; //将字符转化为对应的数值; int getNumberByChar(char ch) { if (NULL != ch) { if ('0' == ch) { return (0); } else if ('1' == ch) { return (1); } else { exit(-3); } } else { exit(-2); } } //将二进制代码转化为unsigned的整型值; unsigned int convertBtoUnsignedD(char * bCode) { if (NULL != bCode && bCode[0] != _STRING_END_FLAG) { unsigned int result = 0; int count = 1; int times = 0; char chBit = bCode[0]; while (chBit != _STRING_END_FLAG) { chBit = bCode[++count]; } for (int i = count - 1; i >= 0; i--) { int number = getNumberByChar(bCode[i]); if (1 == number) { int tempValue = 1; for (int j = 0; j < times; j++) { tempValue *= 2; } result += tempValue; } times++; } return (result); } else { exit(-3); } } //将二进制代码转化为int类型;(带符号的整型) //包含二进制编码的字符串指针; int convertBtoD(char * bCode) { if (NULL != bCode && bCode[0] != _STRING_END_FLAG) { const int MAX_CODE_LENGTH = 20; int result = 0; char chBit = bCode[0]; char strCode[MAX_CODE_LENGTH]; int count = 0; //1、判断二进制代码的符号; if ('1' == bCode[0]) { //如果是负数,那么需要先求其补码; while (chBit != _STRING_END_FLAG) { if (count < MAX_CODE_LENGTH) { //1、逐项取反; strCode[count] = (('0' == chBit) ? '1' : '0'); } else { exit(-1); } chBit = bCode[++count]; } //增加字符串结束标识符; strCode[count] = _STRING_END_FLAG; //2、末项+1; for (int i = count - 1; i >= 0; i--) { if ('0' == strCode[i]) { strCode[i] = '1'; break; } else { strCode[i] = '0'; } } //3、将得到的补码转化成无符号的十进制代码; result = convertBtoUnsignedD(strCode); //4、将绝对值加上符号; return (0 - result); } else { return (convertBtoUnsignedD(bCode)); } } else { exit(-4); } } int main(void) { printf("测试半角字符(即:可以用一个字节表示)的转化情况...\n\n"); short ch = 'F'; //十六进制编码为:46 <=> 0000 0000 0100 0110;十进制编码:70; printf("char: ch = %c\n\n", ch); printf("hex: ch = %#x\n\n", ch); printf("(unsigned char) ch = %u\n\n", (unsigned char)ch); printf("(unsigned) ch = %u\n\n", (unsigned) ch); printf("(short) ch = %d\n\n", (short) ch); printf("ch = %d\n\n", ch); //隐式的(int)ch,结果和(int)ch一致; showSplitLine(); printf("测试全角字符(如:汉字)的转化情况...\n\n"); short wch = '你'; //十六进制编码为:0xC4E3 <=> 1100 0100 1110 0011 //unsigned wch = '你'; printf("char: wch = %c\n\n", wch); //会被截断; printf("hex: wch = %#x\n\n", wch); printf("(unsigned char) wch = %u\n\n", (unsigned char)wch); //由于这里有char进行修饰,所以这里会有截断,仅仅保留最低的8个位(最后一个字节),所以结果为:1110 0011 = 27d printf("(unsigned) wch = %u\n\n", (unsigned) wch); //(unsigned) <=> (unsigned int) 而int是有4个字节保存的,所以会在高位的两个字节补1,从而形成一个很大的数据:4294952163;高位补1(即:按照符号位补充)是因为声明的wch为short是有符号的类型,如果声明为:unsigned short就不会有这个问题; printf("(unsigned short) wch = %u\n\n", (unsigned short) wch); //printf("(short) wch = %d\n\n", (short) wch); printf("wch = %d\n\n", wch); showSplitLine(); printf("从二进制到整型(0000000001000110)\n\n"); //'F'的二进制编码; int result1 = convertBtoD("0000000001000110"); printf("result1 = %d\n\n", result1); printf("从二进制到整型(负数)(1100010011100011)\n\n"); //'你'的二进制编码;(16位, short) int result2 = convertBtoD("1100010011100011"); printf("(signed) result2 = %d\n\n", result2); int result3 = convertBtoUnsignedD("1100010011100011"); printf("(unsigned) result3 = %d\n\n", result3); unsigned int result4 = convertBtoUnsignedD("11111111111111111100010011100011"); //'你'的二进制编码;(32位, int) printf("(unsigned) result4 = %u\n\n", result4); showSplitLine(); return (0); }
myTools.h:
#include <stdio.h> //分割线; void showSplitLine(void) { printf("********************************************************************************\n\n"); return; }
4000
相关文章推荐
- C语言 unsigned 和 signed 类型相互转换深入理解
- C语言中,unsigned与signed类型转换
- C语言中关于char类型存储的分析 以及signed与unsigned的区别
- C语言 unsigned 和 signed 类型相互转换深入理解
- C语言 unsigned 和 signed 类型相互转换深入理解
- C语言 unsigned 和 signed 类型相互转换深入理解
- C语言 unsigned 和 signed 类型相互转换深入理解
- C语言 unsigned 和 signed 类型相互转换深入理解
- char类型默认是signed还是unsigned
- 在C语言中,double、long、unsigned、int、char类型数据所占字节数
- C语言中signed与unsigned的转换
- 在C语言中,double、long、unsigned、int、char类型数据所占字节数
- C语言数据类型的转化
- 在C语言中,double、long、unsigned、int、char类型数据所占字节数
- 在C语言中,double、long、unsigned、int、char类型数据所占字节数
- 练习2-1 编写一个程序一确定分别由signed及unsigned限定的char,short,int及long类型变量的取值范围。采用打印标准头文件中的相应值以及直接计算两种方式实现。通过直接计算来确定浮点类型的取值范围是一项难度很大的任务。
- 在C语言中,double、long、unsigned、int、char类型数据所占字节数
- 在C语言中,double、long、unsigned、int、char类型数据所占字节数
- 在C语言中,double、long、unsigned、int、char类型数据所占字节数
- char, signed char,unsigned char, short int unsigned short int, int数据类型取值问题