当printf以十六进制打印char类型数组时引发的bug

以下代码是我做项目时,遇到的问题,我将以代码出现的问题,进行此次的总结。
代码如下:

/*********************************************************************************
 *      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来打印数据。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章