Char转为int时高位符号扩展的问题

文章完整地址:http://blog.sina.com.cn/s/blog_6bd3c5320101st7l.html

代码示例:

static get_utili(constchar*p){int util;…while(isspace((int)*p))//跳过空格++p;util=(int)*p++;…}

现象&后果:

当传入的参数p指向的内容为0x9A、0XAB等内容(最高位为1)时,得到的int型变量util的值将会出错,因为char会进行符号扩展,使得0x9A(十进制的154)变成了-102。会造成程序运行时的数据处理错误。

Bug分析:

char符号扩展是与编译器相关的,但在x86平台上,对于任何主流的编译平台,char总是进行符号扩展的。上述代码在将char型的*p赋给int型变量util的时候,需要先进行char型到unsigned char型的转换,以避免按照char的最高位进行符号扩展。

上述出错代码的符号扩展过程如下:

因为要扩展的短数据类型为有符号数的-- char x=10011100b(即0x9A)

因而在int y=(int)x时--进行符号扩展,即短数据类型的符号位填充到长数据类型的高字节位(比短数据类型多出的那一部分),则y的值为11111111 10011100b(变成了十进制的-102);

但是,将要扩展的短数据类型变成无符号数后--unsigned char x=10011100b(即0x9A)

在 int y=(int)x时--进行扩展的时候是以零扩展,即用零来填充长数据类型的高字节位,则y的值应为00000000 10011100b(十进制的154)。

正确代码:

util=(int)*p++;改成util=(int)(unsigned char)*p++

Bug定位:

该bug是在code review的过程中发现的。

char符号扩展的问题,如果在测试时没有构造相应的case,就会很难被发现。面对这类问题,细致的code review是必不可少的,不管是通过code review直接发现问题还是通过review来丰富相应case的构造,code review都应该是一个不可缺少的环节。

关于符号扩展

一、短数据类型扩展为长数据类型

1、要扩展的短数据类型为有符号数的

进行符号扩展,即短数据类型的符号位填充到长数据类型的高字节位(即比短数据类型多出的那一部分),保证扩展后的数值大小不变

如1:char x=10001001b; short y=x; y的值应为11111111 10001001b

2char x=00001001b; short y=x; y的值应为00000000 00001001b

2、要扩展的短数据类型为无符号数的

进行零扩展,即用零来填充长数据类型的高字节位

如1:unsigned char x=10001001b; short y=x; y的值应为00000000 10001001b

2unsigned char x=00001001b; short y=x; y的值应为00000000 00001001b

二、长数据类型缩减为短数据类型

如果长数据类型的高字节全为1或全为0,则会直接截取低字节赋给短数据类型;如果长数据类型的高字节不全为1或不全为0,则转会就会发生错误。

三、同一长度的数据类型中有符号数与无符号数的相互转化

直接将内存中的数据赋给要转化的类型,数值大小则会发生变化。另短类型扩展为长类型时,但短类型与长类型分属有符号数与无符号数时,则先按规则一进行类型的扩展,再按本规则直接将内存中的数值原封不动的赋给对方。


你可能感兴趣的:(高位符号扩展)