有符号类型转换为无符号类型
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
看下面的例子: int strlonger(char *s, char *t) {
return strlen(s) - strlen(t) > 0;
2/3
}
上面的函数看起来似乎没什么问题, 实际上当s比t短时,函数的返回值也是1, 为什么会出现这种情况呢? 原来strlen的返回值类型为size_t,C语言中将size_t定义为unsigned int,当s比t短时,str百度文库en(s) - strlen(t)为 负数,但无符号数的运算结果隐式转换为无符号数就变成了很大的无符号数. 为了让函数正确工作,代码应该修改如下 :
二、 #include <stdio.h> int main() {
int a = -2; unsigned int b = 1; printf("a = %d, b = %u\n\n", a, b); if(a > b) {
printf("a > b\n"); } else
1/3
{ printf("a < b\n");
printf("%u\n", a + b)中,由于%u的作用,使a+b以无符号十进制的形式输出,此时,最高位的1并非符号 位,其表示数值大小,不用减一取反,得到1111 1111,实际Linux系统中,该数用4个字节表示,也就是说 实际上这里有16个"1",即十进制数的4294967295(=2^32-1)。
有符号类型转换为无符号类型
有符号类型和无符号类型运算,有符号类型转换为无符号类型
需要注意的有两种情况: 1、有符号和无符号的算术运算 2、有符号和无符号的比较运算
一、 写程序验证有符号类型转换为无符号类型: #include <stdio.h> int main() {
int a = -20; unsigned int b = 6; if((a+b) > 0) {
int len = KSIZE < maxlen ? KSIZE : maxlen; memcpy(user_dest, kbuf, len); retn len; } 你看出了问题所在吗?
3/3
return strlen(s) > strlen(t); 2002年, 从事FreeBSD开源操作系统项目的程序员意识到,他们对getpeername函数的实现存在安全漏洞. 代码的简化版本如下: //void *memcpy(void *dest, void *src, size_t n); #define KSIZE 1024 char kbuf[KSIZE]; int copy_from_kernel(void *user_dest, int maxlen) {
综上,该段程序的输出结果为:
-1
4294967295 =============
C中有符号数与无符号数转化之间的危险
无符号数与有符号数之间存在着很多细节问题,稍有不慎就可能导致程序出现不可预料的错误。
陷阱
在C语言中,如果一个运算包含一个有符号数和一个无符号数,那么C语言会隐式地将有符号数转换为无符 号数,这对于标准的算术运算没什么问题,但是对于 < 和 > 这样的关系运算符来说,它会出现非直观的 结果,这种非直观的特性经常会导致程序中难以察觉的错误
printf("signed to unsigned\n"); } else {
printf("unsigned to signed\n"); } return 0; }
结果为: signed to unsigned 这说明在c语言操作中,如果遇到无符号数与有符号数之间的操作,编译器会自动转化为无符号数来进行处 理。 这个也验证了有符号和无符号算术运算操作时会将有符号类型转换为无符号类型来计算。
int main() {
unsigned int a = 1; signed int b = -2;
printf("%d\n", a + b); printf("%u\n", a + b);
return 0; }
printf("%d\n", a + b)中,由于%d的作用,使a+b以有符号十进制的形式输出,此时,最高位的1为符号 位,减一取反得到其原码,得到1000 0001,即十进制的-1;
}
} 结果: a>b
return 0;
这说明有符号数和无符号数进行比较运算时(==,<,>,<=,>=),有符号数隐式转换成了无符号数(即底 层的补码不变,但是此数从有符号数变成了无符号数),此时的a的值远大于b。
========= 测试的时候需要注意printf的输出参数对结果的影响: #include <stdio.h>
return strlen(s) - strlen(t) > 0;
2/3
}
上面的函数看起来似乎没什么问题, 实际上当s比t短时,函数的返回值也是1, 为什么会出现这种情况呢? 原来strlen的返回值类型为size_t,C语言中将size_t定义为unsigned int,当s比t短时,str百度文库en(s) - strlen(t)为 负数,但无符号数的运算结果隐式转换为无符号数就变成了很大的无符号数. 为了让函数正确工作,代码应该修改如下 :
二、 #include <stdio.h> int main() {
int a = -2; unsigned int b = 1; printf("a = %d, b = %u\n\n", a, b); if(a > b) {
printf("a > b\n"); } else
1/3
{ printf("a < b\n");
printf("%u\n", a + b)中,由于%u的作用,使a+b以无符号十进制的形式输出,此时,最高位的1并非符号 位,其表示数值大小,不用减一取反,得到1111 1111,实际Linux系统中,该数用4个字节表示,也就是说 实际上这里有16个"1",即十进制数的4294967295(=2^32-1)。
有符号类型转换为无符号类型
有符号类型和无符号类型运算,有符号类型转换为无符号类型
需要注意的有两种情况: 1、有符号和无符号的算术运算 2、有符号和无符号的比较运算
一、 写程序验证有符号类型转换为无符号类型: #include <stdio.h> int main() {
int a = -20; unsigned int b = 6; if((a+b) > 0) {
int len = KSIZE < maxlen ? KSIZE : maxlen; memcpy(user_dest, kbuf, len); retn len; } 你看出了问题所在吗?
3/3
return strlen(s) > strlen(t); 2002年, 从事FreeBSD开源操作系统项目的程序员意识到,他们对getpeername函数的实现存在安全漏洞. 代码的简化版本如下: //void *memcpy(void *dest, void *src, size_t n); #define KSIZE 1024 char kbuf[KSIZE]; int copy_from_kernel(void *user_dest, int maxlen) {
综上,该段程序的输出结果为:
-1
4294967295 =============
C中有符号数与无符号数转化之间的危险
无符号数与有符号数之间存在着很多细节问题,稍有不慎就可能导致程序出现不可预料的错误。
陷阱
在C语言中,如果一个运算包含一个有符号数和一个无符号数,那么C语言会隐式地将有符号数转换为无符 号数,这对于标准的算术运算没什么问题,但是对于 < 和 > 这样的关系运算符来说,它会出现非直观的 结果,这种非直观的特性经常会导致程序中难以察觉的错误
printf("signed to unsigned\n"); } else {
printf("unsigned to signed\n"); } return 0; }
结果为: signed to unsigned 这说明在c语言操作中,如果遇到无符号数与有符号数之间的操作,编译器会自动转化为无符号数来进行处 理。 这个也验证了有符号和无符号算术运算操作时会将有符号类型转换为无符号类型来计算。
int main() {
unsigned int a = 1; signed int b = -2;
printf("%d\n", a + b); printf("%u\n", a + b);
return 0; }
printf("%d\n", a + b)中,由于%d的作用,使a+b以有符号十进制的形式输出,此时,最高位的1为符号 位,减一取反得到其原码,得到1000 0001,即十进制的-1;
}
} 结果: a>b
return 0;
这说明有符号数和无符号数进行比较运算时(==,<,>,<=,>=),有符号数隐式转换成了无符号数(即底 层的补码不变,但是此数从有符号数变成了无符号数),此时的a的值远大于b。
========= 测试的时候需要注意printf的输出参数对结果的影响: #include <stdio.h>