이번 포스팅에서는 이전 포스팅에서 언급한 예외 중 OverflowException과 이것을 보기 위한 Checked 키워드에 대해서 정리했습니다.
OverflowException과 Checked 키워드
오버플로우는 자료형이 갖는 최대값을 넘어섰을 때 발생합니다. 예를 들어 정수의 최댓값은 32비트가 표현할 수 있는 최대 수인 2,147,483,647입니다. 만약 이 값을 넘어서는 값이 정수 변수에 할당이 된다면 오버플로우가 발생하게 됩니다. 다음 예제는 오버플로우를 발생시키는 예제입니다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DivideByZero
{
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine("int.MaxValue = {0}", int.MaxValue);
int x = int.MaxValue, y = 0;
y = x + 10;
Console.WriteLine("int.MaxValue + 10 = {0}", y);
}
}
}
int.MaxValue에 10을 더함으로써 오버플로우가 발생했는데 컴파일러는 에러 메세지를 띄우지 않고 엉뚱한 값인 -2147483639를 출력합니다.
결과
int.MaxValue = 2147483647
int.MaxValue + 10 = -2147483639
이런 결과가 나타나는 이유는 이진수 연산의 결과입니다.
int.MaxValue(2,147,483,647) 0111 1111 1111 1111 1111 1111 1111 1111 (32bit)
+ 10 0000 0000 0000 0000 0000 0000 0000 1010 (32bit)
-------------------------------------------------------------------------------
-2147483639 1000 0000 0000 0000 0000 0000 0000 1001
32비트의 비트 패턴의 맨앞자리는 부호를 나타내는 수입니다. 음수를 나타내는 값은 2의 보수로 계산하게 됩니다. 2의 보수를 계산하는 방법은 맨 앞비트를 제외하고 나머지 비트를 반전시킨 뒤 +1을 합니다. 그러면 위의 값은 1111 1111 1111 1111 1111 1111 1111 0111 되어 10진수로 변환하면 -2147483639가 됩니다.
오버플로 메세지를 출력하기 위해서는 try ~ catch문만 사용해서는 안되고 checked 키워드와 함께 사용해야 합니다. 다음은 이에 대한 예제입니다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Overflow
{
internal class Program
{
static void Main(string[] args)
{
int x = int.MaxValue, y = 0;
checked //오버플로 메세지를 보기위해 사용
{
try
{
y = x + 10; //오버플로가 발생한다.
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
Console.WriteLine("int.MaxValue + 10 = {0}", y);
}
}
}
checked 키워드를 사용하면 오버플로 예외를 발생시킵니다. 이 키워드를 사용하지 않으면 디폴트로 unchecked 상태가 되어 결과의 가장 중요한 비트(MSB)가 무시되고 실행이 계속됩니다. 그리고 오버플로가 발생한 변수 값은 0으로 출력됩니다.
결과
산술 연산으로 인해 오버플로가 발생했습니다.
int.MaxValue + 10 = 0
오버플로는 산술연산자 외에도 정수계열간의 형변환이 큰 범위 타입에서 작은 범위 타입으로 이루어지면 (예 : long을 int로 캐스팅) 발생합니다. 그러나 비트 연산이나 시프트 연산은 오버플로를 발생시키지 않습니다.
[Review]
"초보자를 위한 C# 200제(2판)" 저자 / 강병익
'Program Language > C#' 카테고리의 다른 글
Part1. C# 첫발 내딛기(20. String 클래스) (2) | 2023.01.13 |
---|---|
Part1. C# 첫발 내딛기(19. 논리 연산자) (0) | 2023.01.11 |
Part1. C# 첫발 내딛기(17. DivideByZeroException과 try~catch문) (0) | 2023.01.10 |
Part1. C# 첫발 내딛기(16. 산술 연산자) (0) | 2023.01.09 |
Part1. C# 첫발 내딛기(15. C# 연산자와 식) (0) | 2023.01.09 |
댓글