C#/문법 정리

C# - 오버플로우 예외처리 (Overflow Exception)

Khadra 2024. 6. 24. 19:16

C#에서는 실행 중에 나오는 에러를 예외라고 한다.


산술연산에서 나올 수 있는 예외는 0으로 2가지로 분류된다.

  • 나눔 예외처리 (DivideByZeroExeption)
  • 오버플로우 예외처리 (Overflow Exception)

오버플로우 예외처리 (Overflow Exception)

예제 코드

using System;
using static System.Console;//Console단어를 생략(코드길이줄어둠)
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            //int.MaxValue를 출력한다.
            WriteLine("int.MaxValue = {0}", int.MaxValue);

            //int.MaxValue는 부호를 갖는 32비트 정수가 표현할 수 있는 
            //최대값으로  2,147,483,647이다.
            int x = int.MaxValue, y = 0; 

            // int.MaxValue에 10을 더한 값을 y에 할당한다.
            y = x + 10;

            //int의 최대값보다 더 큰 값이므로 오버플로우가 발생한다.
            //출력은 오버플로우 메세지 없지 엉뚱한 값인 -2147483639를 출력한다.
            WriteLine("int.MaxValue + 10 = {0}", y);  
        }
    }
}

결과

int.MaxValue = 2147483647
int.MaxValue + 10 = -2147483639

예제 코드 line:13 계산 결과 설명

  int.MaxValue(2,147,483,647)  0111 1111 1111 1111 1111 1111 1111 1111
+ 10                           1000 0000 0000 0000 0000 0000 0000 1001
---------------------------------------------------------------------
  -2147483639                  1000 0000 0000 0000 0000 0000 0000 1001

즉, 32비트의 비트 패턴은 위와 같이 "1000 0000 0000 0000 0000 0000 0000 1001"인데, 맨 앞자리는 부호를 나타내므로 이 수는 음수이며, -2147483639로 해석(계산)된다.



오버플로 메시지를 표시하기 위해서는 checked 키워드를 사용

예제 코드

using System;
using static System.Console;//Console단어를 생략(코드길이줄어둠)
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            // 이 문장은 컴파일할 때 에러가 난다.
            // 이미 상수 값이 정수의 범위를 넘어선 것을 알 수 있다.
            // y = int.MaxValue + 10; 

            int x = int.MaxValue, y = 0;

            // checked키워드를 사용하면 오버플로 예외를 발생시킨다. 
            // checked를 사용하지 않으면 디폴트로 unchecked 상태가 되어
            // 결과의 가장 중요한 비트(MSB)가 무시되고 실행이 계속된다.
            checked 
            {   
                // try~catch 문으로 예외가 발생하면 어떤 예외인지를 출력한다. 
                try 
                {   
                    y = x + 10;
                }
                catch(Exception e)
                {   
                    // 오버플로가 발생했다는 메세지를 출력한다.
                    WriteLine(e.Message);
                }
            }
            // 오버플로가 발생한 변수 y의 값은 0으로 출력된다.
            WriteLine("int.MaxValue + 10 = {0}", y);
        }
    }
}

결과

Arithmetic operation resulted in an overflow.
int.MaxValue + 10 = 0

정수 오버플로가 발생할 경우

  • 수행되는 작업은 checked 또는 unchecked에 따라 달라진다.
  • checked를 사용하면 OverflowException이 throw가 된다.
  • unchecked 컨텍스트에서는 결과의 가장 중요한 비트가 무시되고 실행이 계속된다.
  • 디폴트는 unchecked이다.

산술연산자 외에도 정수 계열 형식간 캐스팅(예 : long을 int로 캐스팅)할 경우

  • 오버플로를 발생시키고 checked 또는 unchecked 실행이 적용될 수 있다.
  • 비트 연산자와 시프트 연산자는 오버플로를 발생하지 않는다.
  • Decimal 변수의 산술 연산 오버플로는 항상 OverflowException을 throw 한다.
  • Decimal을 0으로 나누면 항상 DivideByZeroExeption이 throw가 된다.