当前位置:C++技术网 > 资讯 > int转为unsigned char类型的警告的分析和解决办法

int转为unsigned char类型的警告的分析和解决办法

更新时间:2018-06-23 12:02:23浏览次数:1+次

        在编译一份代码后,发现一个警告,老是出现,如下:

    warning : conversion to ‘unsigned char’ from ‘int’ may alter its value [-Wconversion]
    出现的太多了,就有点烦了。但是整半天还没有消除,感觉这个警告并不是那么简单,所以决心研究一下,彻底研究清楚,下面就是我的研究成果,分享给大家,值得一读。这个分析可以促进你对类型转换的理解。

        先看一份代码:

    

#include <iostream>
using namespace std;
int main()
{
    unsigned char * p = new unsigned char[10];
    unsigned char index = 3;
    p[0] = 'a' + 3;//无警告
    p[1] = 'a' + index;//warning : conversion to ‘unsigned char’ from ‘int’ may alter its value [-Wconversion]
    p[2] = 'a' + 'b';//无警告
    p[3] = (unsigned char)'a' + index;//warning : conversion to ‘unsigned char’ from ‘int’ may alter its value [-Wconversion]
    p[4] = (unsigned char)('a' + index);//无警告
    p[5] = 'a' + (int)index;//warning : conversion to ‘unsigned char’ from ‘int’ may alter its value [-Wconversion]
    p[6] = 'a' + 300;//warning : large integer implicitly truncated to unsigned type [-Woverflow]
    return 0;
}
    注释后面是编译后的结果,部分没有警告,部分有警告,警告的内容也原样写在注释里了。

    

        我们并不是为了解决一个警告而已,如果是这样,这个问题已经解决了。我们主要是为了深入的研究警告背后的原理,然后可以非常灵活的高效的消除警告,加深我们对类型转换的理解。

        下面开始分析:

    1.类型隐式转换的原理
    存在隐式类型转换的,都会向上转换,而且会上升到大类型。比如char和unsigned char的混合计算,会转到int类计算。如果仅仅拿一个字节来转换,是无法同时容纳char和unsigned char。
    因为char的取值范围是-128 到 127 ,unsigned char的取值范围是0-255,所以总范围是-128到255,一个字节压根就存不下来。所以类型在转换的时候,只能向上提升字节数,也就转到了int类型了。
    而字符char类型和整型int类型的混合计算,就会产生int类型,因为int是可以容纳的最小类型,不需要更大的了。因此最后产生的类型是int。
2.常量计算的转换原理
    常量的混合计算,是预先确定的。常量的值在编译期间是已经确定好了的,编译器自然就可以预先判断结果,来做必要的保护。如果在正常的结果范围内,直接就编译通过,没有警告。如果不在正常范围内,就会报警告。
    警告的内容一般就是数据截断等数据丢失问题。
    字符常量'a'和数字常量3的相加,始终都是可以确定的。类型转换是确定的。如果数值超过了unsigned char的最大值255的话,会报错:
warning : large integer implicitly truncated to unsigned type [-Woverflow] (翻译:大整数会被截断为unsigned类型)
    此时就会真正的警告,而如果整数数字常量在合理的范围内,就不会警告。
    所以以上的问题的问题,我们依次梳理一下(针对每一行代码做一个警告或不警告的解释,可以对此类型转换做一个彻底的了解):

p[0] = 'a' + 300; //字符常量混合计算
p[1] = 'a' + index;//字符常量(char类型)和unsigned char变量的混合计算,因为合并后的范围超出了一个字节的范围,类型提升到int类型,再将int类型转为unsigned char时可能丢失数据而警告
p[2] = 'a' + 'b';//两个char常量的相加,最终得到char常量,再赋值给unsigned char,存在类型转换。但是因为是两个常量,可以预先确定是否存在数据精度丢失问题,此处确定为不存在问题,最终的结果落在unsigned char的范围内,不存在数据丢失问题而不警告。
(unsigned char)'a' + index;//虽然对常量'a'做了类型转换,但是强制的类型转换,有数字常量char转为unsigned char已经将类型提升到了int,再和index混合计算,类型就成了int了。此时会有警告。
p[4] = (unsigned char)('a' + index);//'a' + index的结果虽然被提升为了int类型,但是最终强制转换了类型,所以属于程序员知道的情况,人为处理过了,表示程序员知道这个不会出问题,编译器也不警告了。
p[5] = 'a' + (int)index;//index被强制转为int类型,自然后续的操作会报警告。
    看完之后,我相信,这种警告,就不会再难住你了。