与java语言不同,在C/C++语言中有着有符号数与无符号数的概念,有符号数可以表示正数、0、负数,无符号数只能表示非负数。数据位数相同的有符号数和无符号数所能表示的数据个数是一样的,但由于有符号数最高位为符号位,两者表示的数字的区间不同。例如,char和unsigned char在内存中都占用8个字节,最多能表示2^8也就是256个数字,char表示的范围为[-128, 127],unsigned char表示的范围为[0, 255]。
有符号数的表示方法
有符号数据类型(比如int、long)的最高位用于标识数据的符号,
最高位为1,表明这个数是负数。
最高位为0,表明这个数是正数。
以下程序所示
int main(void) {
char c = -11;
short s = 5;
int i = -7;
printf("%d\n", (c & 0x80) == 0);
printf("%d\n", (s & 0x8000) == 0);
printf("%d\n", (i & 0x80000000) == 0);
return 0;}
输出结果为
0
1
0
0x80是8位无符号数,char c转化为无符号数后,最高位为符号位1,故c & 0x80 == 0x80
计算机内部用补码表示有符号数
正数的补码为正数本身
负数的补码为负数的绝对值各位取反后加1
8位整数5的补码为: 0000 0101
8位整数-7的补码为:1111 1001 计算过程 7–> 0000 0111 –>1111 1000 -> 1111 1001
16位整数20的补码为: 0000 0000 0001 0100
16位整数-13的补码为:1111 1111 1111 0011
计算过程13–> 0000 0000 0000 1101 –>1111 1111 1111 0010 -> 1111 1111 1111 0011
无符号数的表示方法
在计算机内部用原码表示无符号数,无符号数没有符号位,只用于表示正数。
无符号数默认为为正数,没有符号位。
对于固定长度的无符号数,
-MAX_VALUE + 1 = MIN_VALUE(0)
-MIN_VALUE - 1 = MAX_VALUE(FFF…FFF)
C语言中的变量默认为有符号类型
unsigned关键字声明变量为无符号类型
C语言中只有整数类型能够声明为unsigned变量,比如char、int、short这些可以有对应的unsigned char、unsigned int、unsigned short,而float、double这些本身就是带符号的。
有符号数和无符号数进行运算
当无符号数和有符号数进行运算时,有符号数会转化为无符号数再参与运算。
如以下程序所示
int main(void) {
int i = -10;
unsigned int j = 5;
printf("-10 + 5 = %d\n", i + j);
if ( (i + j) > 0 )
{
printf("-10 + 5 > 0\n");
} else {
printf("-10 + 5 <= 0\n");
}
return 0;
}
输出结果为
i + j = -5
-10 + 5 > 0
其原因是int型的i与unsigned int型的 j进行运算时,会将i转化为unsigned int类型,也就是一个很大的正整数,所以-10 + 5 > 0,而-10 + 5 = -5则是因为“%d”是c语言中printf函数中定义的有符号数的符号,这里输出是又将相加后这个很大的整数转化为有符号数。
无符号数的最小值为0,最小值-1将变成最大值。以下程序将会进入无限循环。
int main(void) {
for ( unsigned int i = 5; i >= 0; i-- ) {
printf("i = %d\n", i);
}
return 0;
}