您的位置:首页 > 其它

字符溢出分析(数据类型范围以及‘\0’重新认识)

2015-09-14 17:00 453 查看
#include <iostream>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
char a[1000];
int i;
for (i=0;i<1000;i++)
{
a[i] = -1-i;
}
cout<<strlen(a)<<endl;
system("pause");
return 0;
}


做题目的时候没有考虑到字符溢出,自然做错了

【分析】

我们知道计算机底层只认识0,1,所以任何数据到了底层都会通过计算转换成0,1,那么负数是怎样存储呢?由于“-”无法存入内存,我们把它做个标记,把基本数据类型的最高位腾出来,用来存符号,同时约定如下:如果最高位是1,表明这个数是负数,其值为除最高位以外的剩余位的值添上这个“-”号。

bool型为布尔型,占1个字节,取值0或1。
BOOL型为int型,一般认为占4个字节,取值TRUE/FALSE/ERROR。

sbyte型为有符号8位整数,占1个字节,取值范围在128~127之间。

bytet型为无符号16位整数,占2个字节,取值范围在0~255之间。

short型为有符号16位整数,占2个字节,取值范围在-32,768~32,767之间。

ushort型为无符号16位整数,占2个字节,取值范围在0~65,535之间。

int型为有符号32位整数,占4个字节,取值范围在-2,147,483,648~2,147,483,647之间。

uint型为无符号32位整数,占4个字节,取值范围在0~4,294,967,295之间。

long型为64位有符号整数,占8个字节,取值范围在9,223,372,036,854,775,808~9,223,372,036,854,775,807之间。

ulong型为64位无符号整数,占8个字节,取值范围在0~18,446,744,073,709,551,615之间。

float型为32位单精度实数,占4个字节,取值范围3.4E+10的负38次方~3.4E+10的38次方之间。

double型为64位实数,占8个字节,取值范围1.7E+10的负308次方~1.7E+10的正308次方。


for循环内,当i的值为0时,a[0]的值为-1.在计算机系统中,数值一律用补码来表示。在用两个补码的数相加时,如果最高位(符号位)有进位,则进位被舍弃。正数的补码与其原码一致;负数的补码:符号位为1,其余位为该数绝对值的原码按位取反,然后整个数+1.

-1的补码为0xff,-2的补码为0xfe……

当i的值为127时,a[127]的值为-128,而-128是char类型数据能表示的最小的负数。

当i继续增加,a[128]的值肯定不能使-129,因为这时候发生了溢出。-129需要9位(1 1000 0001)才能存储下来,而char只有8位,所以最高位被丢弃,剩下的8位是原来9位补码(1 111 1111)的低8位的值,即0x7f。当i继续增加到255时,-256的补码低8位全为0,然后当i增加到256时,-257的补码的低8位全为1,即低8位的补码为0xff,如此又开始一轮新的循环……

按照上面的分析,a[0]~a[254]里面的值都不为0,而a[255]的值我0.

‘\0’ 的ASCII值为0。

strlen函数是计算字符串长度的,并不包含字符串最后的’\0’。判断一个字符串是否结束的标志就是看是否遇到’\0’;如果遇到’\0’,则认为字符串结束。

由此分析,strlen(a)的值为255。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  字符溢出 ASCII