首页 > 代码库 > 关于操作有符号数的溢出问题

关于操作有符号数的溢出问题

在计算机中,数值的二进制表示方法主要有:原码、反码和补码。通常取最高位为符号位,0表示正数,1表示负数。正数的原码、反码、补码一样。而负数的原码最高位取1,数值位取负数绝对值的二进制值;反码的符号位为1,其余位取反;补码的符号位为1,其余位取反加1。

在32位计算机中,有符号字符型变量的取值范围是-27 ~ 27-1,有符号整型变量的取值范围是-215~ 215-1,如果将有符号整型变量赋给有符号字符型变量,则高位被截断,保留低八位。

看一个例子:

#include<stdio.h>
#include<string.h>

int main()
{
	char a[1000];
	int i;
	for(i = 0; i < 1000; i++)
	{
		a[i] = -1 - i;
	}
	printf("%d\n", strlen(a));
	return 0;	
}

语句a[i] = -1 – i ;将有符号整型变量赋给有符号字符型变量,当0 <= i <=127时,不会溢出,a[i]从-1变到-128,当i = 128时,- 1 - i = -129。-129的原码形式是:

1000 0000 0000 0000 0000 00001000 0001;补码形式是

1111 1111 1111 1111 1111 11110111 1111;此时将其赋给signed char类型的a[128]时,发生溢出,只保留低八位0111 1111,即127。之后随着i的增加,a[i]从127逐渐向0靠近,当I = 254时,-1 – I =-255,补码表示是:1111 1111 1111 1111 1111 1111 0000 0001,此时a[254] = 1。当i = 255时,a[255] = 0,即将ASCII码为0的值赋给字符型数组元素a[255]。随后a[i]又是从-1 ~ -128,再从127 ~ 0之间反复变化。

而strlen函数是求取字符串的实际长度,当遇到第一个空字符’\0’时,返回,所以strlen(a) = 255。


PS:空字符’\0’(ASCII码值为0)、零字符’0’(ASCII码值为48)。

2014年8月10日星期日