以下代码是我做项目时,遇到的问题,我将以代码出现的问题,进行此次的总结。
代码如下:
/*********************************************************************************
* Copyright: (C) 2020 makun<[email protected]>
* All rights reserved.
*
* Filename: char.c
* Description: This file
*
* Version: 1.0.0(2020年05月14日)
* Author: makun <[email protected]>
* ChangeLog: 1, Release initial version on "2020年05月14日 18时30分44秒"
*
********************************************************************************/
#include <stdio.h>
void dump_buf(char *buf, int bytes);
int main (int argc, char **argv)
{
char buf[5]={0xfd,0xfe,0xff,0xff,0xff};
dump_buf(buf, 5);
return 0;
}
//该函数是以十六进制打印buf数组中的值
void dump_buf(char *buf, int bytes)
{
int i;
for(i=0; i<bytes; i++)
{
printf("0x%02x ", buf[i]);
if( 0 == (i+1)%16 )
printf("\n");
}
printf("\n");
}
预期结果:
0xfd 0xfe 0xff 0xff 0xff
实际结果:
0xfffffffd 0xfffffffe 0xffffffff 0xffffffff
下面图片为运行后的结果即是实际结果
这是我做项目遇到的一个问题,让我百思不得奇解,为什么会和我预想的不一样那?于是我就把项目中的这个问题拿出来单独测试,当我用实验室服务器写的时候它竟然跟预期的一样,代码跟如上一样,运行结果如下:
我就觉得这个问题是偶然得,有时候他会出现这样得错误,有时候不会出现这样得错误,前面得代码没问题,应该问题是出在用dump_buf函数以十六进制输出,当我用printf("0x%02x ",(unsigned char) buf[i]);输出时,这个问题就解决了。
对此我开始百度当十六进制打印char和unsigned char为什么它们得结果会不一样,然后就找到了自己想要的答案,对此,我想把我这次学到得知识记录在这里,供自己学习。我们先学习一下char和unsigned char的区别吧
char和unsigned char的区别
在内存中,char与unsigned char没有什么不同,都是一个字节,唯一的区别是,char的最高位为符号位,因此char能表示-128~127, unsigned char没有符号位,因此能表示0~255,这个好理解,8个bit,最多256种情况,因此无论如何都能表示256个数字。
在实际使用过程种有什么区别呢?
主要是符号位,但是在普通的赋值,读写文件和网络字节流都没什么区别,反正就是一个字节,不管最高位是什么,最终的读取结果都一样,只是你怎么理解最高位而已,在屏幕上面的显示可能不一样。
但是我们却发现在表示byte时,都用unsigned char,这是为什么呢?
首先我们通常意义上理解,byte没有什么符号位之说,更重要的是如果将byte的值赋给int,long等数据类型时,系统会做一些额外的工作。
如果是char,那么系统认为最高位是符号位,而int可能是16或者32位,那么会对最高位进行扩展(注意,赋给unsigned int也会扩展)而如果是unsigned char,那么不会扩展。
对于上面这样的理解我想大家应该理解了吧 ,为什么当字节0xfd以有符号和无符号的char打印时值不一样了吧。当把char里的值以十六进制打印时,系统认为最高位是符号位, printf里隐含地做了一个char到int的转换,将扩充的位被填充成符号位,符号位为0和1,因为以十六进制所以打印的值为0xfffffffd,ff是十六进制而它的二进制是1111 1111 ,剩下两个ff的二进制也是一样的都被填充成了1.
对于以上这个bug是偶然的,但是作为一个合格的程序员,应该在无论如何要注意这个细节上的问题,毕竟常言:细节决定成功,所以当我们写代码时遇到这种问题,一定要用unsigned char来打印数据。