有符号数与无符号数
符号转换:C语言允许在各种不同的数字数据类型之间做强制类型转换,强制类型转换的结果保持位值不变,只是改变了解释这些位的方式,C语言支持所有整型数据类型的有符号和无符号运算,大多数数字都默认为是有符号的,要创建一个无符号常量,必须加上后缀字符U。
short int y = -12345;
unsigned short uv = (unsigned short) v;
printf("v = %d, uv = %u\n", v, uv);
当执行一个运算时,如果它的一个运算数是有符号的而另一个是无符号的,那么C语言会 隐式地将有符号参数强制类型转换为无符号数,并假设这两个数都是非负的,来执行这个运算。对于像<和>这样的关系运算符来说,会导致非直观的结果。
扩展数位:不同字长的整数之间转换,同时又保持数值不变。
将一个无符号数转换为一个更大的数据类型,我们只需要简单地在表示的开头添加0,这种运算称为零扩展。
将一个补码数字转换 为一个更大的数据类型可以执行符号扩展,添加最高有效位的值。位向量[101]表示值-4+1=-3。对它应用符号扩展,得到位向量[1101],表示的值-8 + 4+1 =-3。我们可以看到,对于w=4,最高两位的组 合值是-8+4=-4,与w=3时符号位的值相同。
当把short转换成unsigned时,我们先要改变大小,之后再完成从有符号到无符号的转换。
补充:Tmin的特殊写法,TMin32写成-2147483647-1, 补码表示的不对称性和C语言转换规则之间这种奇怪的交互,迫使我们用这种 不寻常的方式来写TMin32。
limits.h头文件
/* Minimum and maximum values a ‘signed int’ can hold. */
#define INT.MAX 2147483647
#define INT.MIN (-INT_MAX - 1)
截断:将-一个w位的数截断为一个k位数字时,我们会丢弃高w-k位,
函数getpeername的安全漏洞:
/*
* Illustration of code vulnerability similar to that found in
* FreeBSD * s implementation of getpeername()
*/
/* Declaration of library function memcpy */
void *memcpy(void *dest, void *src, size_t n);
/* Kernel memory region holding user-accessible data */
#define KSIZE 1024;
char kbuf[KSIZE];
/* Copy at most maxlen bytes from kernel region to user buffer .*/
int copy_from_kernel(void *user_dest, int maxlen) {
/* Byte count len is minimiim of buffer size and maxlen */
int len = KSIZE <maxlen ? KSIZE:maxlen;
memcpy(user.dest, kbuf, len);
return len;
}
第7行给出的是库函数memcpy的原型,这个函数是要将一段指定长度为n 的字节从存储器的一个区域复制到另一个区域。函数copy_from_kernel 要将一些操作系统内核维护的数据复制到指定的用户可以访问的存储器区域。
调用copy_from_kernel的代码中对maxlen使用了负数值,那么,第16行的最小值计算会把这个值赋给Len,然后,Len会作为参数n被传递 给memcpy,参数n是被声明为数据类型size_t的。这个数据类型是在库文件 stdio.h中(通过typedef)被声明的。在32位机器上被定义为unsigned int。参数n是无符号的, memcpy会把它当作一个非常大的正整数,并且试图将这样多字节的数据从内核区域复制到用户的缓冲区。虽然复制这么多字节,实际上不会完成, 因为程序会遇到进程中非法地址的错误,但是程序还是能读到没有被授权的内核存储器区域。避免这类错误的一种方法就是绝不使用无符号数。实际上,除了 C 以外,很少有语言支持无符号整数。
练习:
答案:
x | 二进制 | T2U4(x) |
-8 | 1000 | 8 |
-3 | 1101 | 13 |
-2 | 1110 | 14 |
-1 | 1111 | 15 |
0 | 0000 | 0 |
5 | 0101 | 5 |
答案:将十进制化为补码形式再以无符号的形式解读
答案:
无符号数,1
有符号数,1
无符号数,0
有符号数,1
无符号数,1
答案: A=-8+3=-5
B=-16+8+3=-5
C=-32+16+8+3=-5
答案:
w | fun1(w) | fun2(w) |
0x00000076 | 0x00000076 | 0x00000076 |
0x87654321 | 0x00000021 | 0x00000021 |
0x000000c9 | 0x000000c9 | 0xFFFFFFc9 |
0xEDCBA987 | 0x00000087 | 0xFFFFFF87 |
答案:
无符号:0,2,1,3,7
补码:0,2,1,3,-1
答案:因为i会转换为无符号数,则i的值永远大于0,将length设置为signed。
答案:
A:当有符号数与无符号数进行比较是会产生不正确的结果。
B:因为有符号数会转换为无符号数,其值非我们的预设值。
C:将size_t设置为int。