C语言程序输出数据溢出问题

C语言程序输出数据溢出问题,第1张

在c语言中,数据的存储就像一个圆圈,正数溢出数据就会从最小负数开始,负数溢出数据同理,打个比方(简略写一下):

int

a=32768,b=-32769;

printf("a=%d,b=%d",&a,&b)

则会输出a=-32768,b=32767

这样则50000输出就是(50000-32767)+(-32768)+(-1)=-15536

1、溢出:

数据类型超过了计算机字长的界限而出现的数据溢出;

2、溢出可能原因:

当应用程序读取用户数据,复制到应用程序开辟的内存缓冲区中,却无法保证缓冲区的空间足够时 (假设定义数组int Array[10], 而在调用时使用Array[11] 或存放的数据超过int类型容量等), 内存缓冲区就可能会溢出.

3、溢出因素分析:

由于C/C++语言所固有的缺陷,既不检查数组边界,又不检查类型可靠性,且用C/C++语言开发的程序由于目标代码非常接近机器内核,因而能够直接访问内存和寄存器,只要合理编码,C/C++应用程序在执行效率上必然优于其它高级语言。然而,C/C++语言导致内存溢出问题的可能性也要大许多。

C

中调用积运算符之后做溢出检测已经太晚,但调用和运算符之后做检测则一点也不迟,

所以你可以通过对和运算结果的检测实现能检测溢出的积运算,因为

a

*

b

既是

a

b

的和:

-5000000

*

1374389539

等于

-(5000000

*

1374389539)。括号里是

5000000

1374389539

的和。

我把能检测溢出的和运算包在

add(

)

里,然后在

multiply(

)

里重复调用

add(

)。

add(

)

怎么检测溢出?

和运算的结果若溢出将导致数值的环绕。上溢导致往下环绕,下溢导致往上环绕。

边界状况:

(1)最轻微的上溢是

INT_MAX

+

1

:结果是

INT_MIN。

(2)最严重的上溢是

INT_MAX

+

INT_MAX

:结果是

-2。

(3)最轻微的下溢是

INT_MIN

-

1

:结果是

INT_MAX。

(4)最严重的下溢是

INT_MIN

-

INT_MIN

:结果是

0。

结论:

(1)所有上溢结果都小于任何一个 *** 作数。

(2)所有下溢结果都大于任何一个 *** 作数。

所以

add(

)

可以用结果和任意选定的一个参数判断溢出,并以落选的参数判断溢出的方向。

add(

)

无法以返回值举报溢出,所以采用

strtol(

)

的举报方法。

不同于

strtol(

)

的是,若没有溢出,add(

)

会把

0

赋值给

errno。

multiply(

)

在这方面跟

add(

)

一样。

#include<stdio.h>

#include<errno.h>

/*

errno,

ERANGE

*/

/*

*

Returns

the

sum

of

a

and

b,

with

overflow

and

underflow

check.

*

If

overflow

or

underflow

occurred,

sets

errno

to

ERANGE,

else

to

0.

*/

int

add(

int

a,

int

b

)

{

int

result

=

a

+

b

if(

b

>

0

&&

result

>

a

||

b

<=

0

&&

result

<=

a

)

errno

=

0

else

errno

=

ERANGE

return

result

}

/*

*

Returns

the

product

of

a

and

b

obtained

through

repeated

call

of

add(

).

*

Affects

errno

exactly

as

add(

)

does.

*/

int

multiply(

int

a,

int

b

)

{

int

sign_of_a

=

1,

result

=

0,

i

=

0

/*

Keep

the

sign

of

multiplier

off

the

loop

sentinel.

*/

if(

a

<

0

)

{

sign_of_a

=

-1

a

*=

-1

}

/*

Have

to

reset

errno

here

because

it

won't

be

updated

if

a

is

0.

*/

errno

=

0

while(

i++

<

a

)

{

result

=

add(

result,

b

)

if(

errno

==

ERANGE

)

break

}

return

result

*

sign_of_a

}

int

main(

)

{

int

result

/*

Operands

too

huge:

sure

overflow.

*/

result

=

multiply(

-5000000,

1374389539

)

if(

errno

==

ERANGE

)

perror(

"Uh

oh"

)

else

printf(

"%d\n",

result

)

/*

Small

operands:

safe.

*/

result

=

multiply(

49,

-972

)

if(

errno

==

ERANGE

)

perror(

"Uh

oh"

)

else

printf(

"%d\n",

result

)

}

当然,应付溢出的最佳方法还是防范:充分了解数据的范围,选择恰当的变量类型。

也许你正考虑改用不需要你担心整数类型溢出的语言。考虑过

Python

吗?


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/11988753.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-20
下一篇 2023-05-20

发表评论

登录后才能评论

评论列表(0条)

保存