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

在计算机中,数值的二进制表示方法主要有:原码、反码和补码。通常取最高位为符号位,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
", 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函数是求取字符串的实际长度。当遇到第一个空字符’’时,返回,所以strlen(a) = 255。


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

2014年8月10日星期日

原文地址:https://www.cnblogs.com/slgkaifa/p/6776337.html