본문 바로가기
Program Language/C#

Part1. C# 첫발 내딛기(18. OverflowException 과 Checked 키워드)

by 토담이아빠 2023. 1. 11.

 

이번 포스팅에서는 이전 포스팅에서 언급한 예외 중 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판)" 저자 / 강병익

댓글