게임 개발/C++

[C++] 캐스팅 - 1. C 스타일 캐스팅

유행성바코드 2025. 3. 4. 22:20

목차

  • 01. Intro
  • 02. 캐스팅
    • C 스타일 캐스팅
    • C++ 스타일 캐스팅
  • 03. C 스타일 캐스팅
    • 사용 예시
    • C 스타일 캐스팅 지양 이유
  • 04. 마무리
  • 05. 연관 내용

01. Intro

오늘은 캐스팅(Casting)과 C스타일 캐스팅에 대해서 알아보겠습니다.

 


02. 캐스팅

캐스팅은 타입 변환을 의미합니다.

 

큰 종류로는 C 스타일 캐스팅과 C++ 스타일 캐스팅이 있습니다.

 

C 스타일 캐스팅

#include <iostream>

using namespace std;

int main()
{
	float f = 1.2345f;
    
    	// C 스타일 캐스팅
    	int i = (int)f;
}

C 스타일 캐스팅은 위 코드처럼 단순히 괄호를 사용해서 타입을 변환합니다.

 

C++ 스타일 캐스팅

C++에서 사용하는 주요 스타일 캐스팅은 총 4가지가 있습니다.

 

1. static_cast

2. dynamic_cast

3. const_cast

4. reinterpret_cast

 

C++ 스타일 캐스팅은 추후에 알아보도록 하겠습니다.


03. C 스타일 캐스팅

 

C 스타일 캐스팅은 앞서 말한 것처럼 단순히 괄호를 사용해서 타입을 변환합니다.

 

 

사용 예시

#include <iostream>

using namespace std;

int main()
{
    float f = 1.2345f;

    // C 스타일 캐스팅
    int i = (int)f;

    cout << i << "\n";

    return 0;
}

위 코드를 실행하면, 정수 뒤의 소수점 값이 모두 버려지는 걸 확인할 수 있습니다.

따라서, 실수형에서 정수형으로 바뀌었으므로 캐스팅이 정상적으로 작동했음을 알 수 있습니다.

 

이러한, 기본 자료형 변환뿐만 아니라 포인터 자료형 변환, 클래스형 변환, const 형변환도 가능합니다.

하지만, C 스타일 캐스팅보다는 C++ 스타일 캐스팅을 사용해야 합니다.

 

그렇다면, 왜 C 스타일 캐스팅을 피해야 하는지 한 번 알아보겠습니다.

 

 

C 스타일 캐스팅 지양 이유

1. const가 정상적으로 작동하지 않을 수 있습니다.

#include <iostream>

using namespace std;

int main()
{
	const int i = 50;
	int* p = (int*)&i;

	*p = 100;

	cout << i << endl;
    	cout << *p << endl;

	return 0;
}

위 방식으로 코드를 사용하면, p 포인터 변수는 i에 대한 주소값을 가지고 있습니다.

분명히, p가 가리키고 있는 객체의 값을 변경했으나 서로 다른 값이 출력됩니다.

이는 컴파일러 최적화를 통해서 이를 방지하기 때문입니다.

 

그래서, 실제로 메모리로 i 변수의 주소로 이동해 보면, 100의 값을 가지고 있습니다.

 

 

그렇다면, 컴파일러 최적화를 막고, 항상 메모리에서 값을 읽도록 강제하는 코드로 확인해 보겠습니다.

#include <iostream>

using namespace std;

int main()
{
	volatile const int i = 50;
	int* p = (int*)&i;

	*p = 100;

	cout << i << endl;
	cout << *p << endl;

	return 0;
}

위 코드로 실행하면, const 키워드를 사용해서 상수로 지정했음에도 값이 변경됩니다.

 

여담으로 volatile 키워드에 대해서는 추후에 알아보도록 하겠습니다.

 

2. 위험한 포인터 타입 변환

#include <iostream>

using namespace std;

int main()
{
	int i = 50;
	double* d = (double*)&i;

	cout << i << endl;
	cout << *d << endl;

	return 0;
}

위 코드를 실행하면, 잘못된 타입 캐스팅으로 해석이 이상하게 나옵니다.

하지만, 실제로 변수 i의 주소로 이동하면 값은 정상적으로 50을 가지고 있습니다.

 

이는 int형과 double형의 메모리 저장 방식이 서로 다르기 때문에 발생합니다. 

변수형에 대한 메모리 저장 방식은 추후에 다루도록 하겠습니다.

 

3. 잘못된 부모-자식 클래스 변환

#include <iostream>

using namespace std;

// 부모 클래스
class Sport
{
public:
	Sport() : _num(0) {}

	int _num;
};

// 자식 클래스
class Soccer : public Sport
{
public:
	Soccer() : _player(22) {}

	int _player;
};

int main()
{
	// 다운캐스팅
	Sport* sport = new Sport();
	Soccer* soccer = (Soccer*)sport;
	
	// 변수값 출력
	cout << soccer->_num << endl;
	cout << soccer->_player << endl;

	return 0;
}

Sport 클래스 객체를 동적 할당하고 sport 포인터는 Sport 클래스 객체의 주소값을 가지고 있습니다.

이때, sport 포인터를 강제로 soccer 포인터 변수형으로 변환합니다.

 

soccer 포인터가 가지는 주소값은 실제로 Sport 클래스 객체이지만, Soccer* soccer이므로 Soccer 클래스 객체라고 인식합니다.

그러므로, Soccer 클래스의 변수에도 접근할 수 있습니다.

이때, _player 변수에 대해 초기화가 되지 않았으므로 잘못된 값을 출력합니다.

 

따라서, 잘못된 다운캐스팅으로 메모리 오염이 발생할 수 있습니다.

 

Undefined Behavior (UB)

위 세 가지의 C 스타일 캐스팅을 Undefined Behavior(UB) 즉, 정의되지 않은 동작이라고 합니다.

이는 C++에서 프로그램이 표준에서 정의되지 않은 동작을 수행할 때, 발생하는 것으로 예상치 못한 결과가 나올 수 있습니다.

따라서, C 스타일 캐스팅은 피하는 것이 좋습니다.

 

추가로, UB는 이러한 상황 외에도 정수 나누기 0 나누기, 배열 범위 초과 접근, 와일드 포인터 문제, Use-After-Free, 정수 오버플로우 등도 포함됩니다.


04. 마무리

오늘은 캐스팅 중에서 C 스타일 캐스팅에 대해서 알아봤습니다.

C 스타일 캐스팅을 지양하는 중 가장 큰 이유가 위와 같은 위험한 캐스팅을 진행했을 때, 별도의 오류를 출력하지 않는 점이 가장 큽니다. 

 

그래서, 다음 포스팅 글부터는 C++ 스타일 캐스팅에 대해서 하나씩 알아보도록 하겠습니다.

 

 


05. 연관 내용

  • [C++] 캐스팅 - 2. static_cast
 

[C++] 캐스팅 - 2. static_cast

목차01. Intro02. static_cast사용 예시C 스타일 캐스팅 vs static_cast03. 마무리04. 연관 내용01. Intro오늘은 C++ 스타일 캐스팅 중에서 static_cast에 대해 알아보겠습니다. 02. static_caststatic_cast는 C++ 스타일 캐

epidemic-barcode.tistory.com

  • [C++] 캐스팅 - 3. dynamic_cast
 

[C++] 캐스팅 - 3. dynamic_cast

목차01. Intro02. dynamic_cast정의 및 특징예시성능03. 마무리04. 연관 내용01. Intro오늘은 C++ 스타일 캐스팅 중에서 dynamic_cast에 대해 알아보겠습니다. 02. dynamic_cast정의 및 특징dynamic_cast는 런타임 타임

epidemic-barcode.tistory.com

  • [C++] 캐스팅 - 4. const_cast
 

[C++] 캐스팅 - 4. const_cast

목차01. Intro02. const_cast정의 및 특징사용 예시주의점03. 마무리04. 연관 내용01. Intro오늘은 C++ 스타일 캐스팅 중에서 const_cast에 대해 알아보겠습니다.  02. const_cast 정의 및 특징const_cast는 const 속

epidemic-barcode.tistory.com

  • [C++] 캐스팅 - 5. reinterpret_cast
 

[C++] 캐스팅 - 5. reinterpret_cast

목차01. Intro02. reinterpret_cast정의 및 특징사용 예시03. 마무리04. 연관 내용01. Intro오늘은 C++ 스타일 캐스팅 중 마지막인 reinterpret_cast에 대해 알아보겠습니다. 02. reinterpret_cast정의 및 특징reinterpret_c

epidemic-barcode.tistory.com

 

 


 

읽어주셔서 감사합니다.

틀린 내용 지적은 언제나 환영입니다!