A. c語言溢出判斷問題
#include<inttypes.h>
#include<stdio.h>
int main()
{
int t;
uint64_t a, b;
scanf("%d", &t);
for(int i=0; i<t; i++)
{
scanf("%" SCNu64 "%" SCNu64, &a, &b);
printf("%d\n", a+b<a);
}
return 0;
}
B. c語言溢出判斷
#include<stdio.h>
intmain()
{unsignedinta=0,c,n,c1,i;
scanf("%u",&n);
c=1;
for(i=1;i<=n;i++)
{c*=i;
if(c<c1)
{printf("unsignedint最大可以計算%u以內的階乘。
%u!=%u
s(%u)=%u",i-1,i-1,c1,i-1,a);
break;
}
a+=i;
c1=c;
}
return0;
}
C. 在C語言中怎樣判斷一個程序運算結果是否溢出,舉個例子,你用C語言編寫程序求n!,判斷n為幾時n!溢出
#include<stdio.h>
unsignedf(unsigned*n){
unsignedi=2,res=1,lres=1;
while(1){
lres*=i;
if(lres<res){
*n=i-1;
returnres;//溢出後,階乘的結果會變小。
}
res=lres;
i++;
}
returni;//本行是不會執行的,這是為了函數需要返回值而設的。
}
intmain(){
unsignedn;
printf("%u!=%u ",n,f(&n));
return0;
}
D. 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
proct
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
嗎?
E. C語言溢出判斷
這個是用VC6寫的控制台程序中從2147483644開始累加的數列,可以看出溢出的時候沒有任何錯誤提示:
2147483644
2147483645
2147483646
2147483647
-2147483648
-2147483647
-2147483646
-2147483645
-2147483644
-2147483643
-2147483642
這個是我寫的可以判斷溢出的加法函數:
#include
<stdio.h>
int
uoadd
(int
a,int
b,int
*overflow);
int
overflow;
int
main
()
{
int
a=2147483647-9,b=10,c=0;
c=uoadd(a,b,&overflow);
if
(overflow
==
1)
printf
("溢出!\n");
else
printf
("%d\n",c);
return
(0);
}
int
uoadd
(int
a,int
b,int
*overflow)
{
*overflow=0;
if
(a>0
&&
b>0
&&
a+b<0)
*overflow=1;
if
(a<0
&&
b<0
&&
a+b>0)
*overflow=1;
return
(a+b);
}
VC6編譯,新建工程的時候選控制台程序
其實其他的應用程序可能會內置判斷溢出的東西,比如VB就會判斷,如果數據溢出了就會彈出一個對話框,其他的就不知道了
其實這個東西用匯編解決相當容易了,但考慮到可讀性還是用C比較好