reinterpret_cast

Jaemyeong Lee·2024년 11월 8일
0

FastCampusC++

목록 보기
77/78

이 코드를 한 줄씩 분석하여 설명드리겠습니다.

#include <iostream>
#include <cfloat>

using std::cout;
using std::endl;
  • #include <iostream>: 입출력 라이브러리를 포함하여 콘솔 출력(cout)을 사용할 수 있게 합니다.
  • #include <cfloat>: FLT_TRUE_MIN과 같은 상수들을 제공하는 헤더로, float 타입의 최소 양수 값 등과 관련된 상수들을 사용할 수 있게 합니다.
  • using std::cout;using std::endl;: std 네임스페이스에 있는 coutendl을 직접 사용하도록 지정하여, std::cout 대신 cout만으로도 사용할 수 있게 합니다.
union ID
{
    char chars[10];
    int integer;
};
  • union ID: union은 모든 멤버 변수가 동일한 메모리 위치를 공유하도록 합니다. 즉, chars 배열과 integer 변수가 같은 메모리 공간을 차지하며, 하나의 변수를 쓰면 다른 변수도 영향을 받습니다.
  • char chars[10];: 10바이트 크기의 char 배열로, 문자열 또는 문자 데이터를 저장할 수 있습니다.
  • int integer;: 4바이트 크기의 정수형 변수로, 정수를 저장할 수 있습니다. union 특성상 integer를 사용하면 chars 배열과 메모리를 공유하게 됩니다.
int main()
{
    ID id;
    id.integer = 10;
  • ID id;: ID 타입의 union 변수 id를 선언합니다.
  • id.integer = 10;: idinteger 멤버에 10을 할당합니다. union은 메모리를 공유하므로 integer에 값을 넣으면 chars 배열도 이 값을 바탕으로 변경됩니다.
    // 해당 비트 배열을 int로 인식하겠다는 의미
    // 사용에 주의
    int* p = reinterpret_cast<int*>(&id);
    cout << *p << endl;
  • int* p = reinterpret_cast<int*>(&id);: id의 주소를 int* 타입으로 재해석하여 포인터 p에 할당합니다. reinterpret_cast는 단순히 데이터 타입을 강제로 바꾸는 역할을 하므로, id가 가진 integer의 값이 p 포인터로 접근되게 됩니다.
  • cout << *p << endl;: p가 가리키는 주소의 값을 출력합니다. 이 경우, id.integer에 10을 할당했으므로 10이 출력됩니다.
  • reinterpret_cast는 메모리를 강제로 다른 타입으로 변환하는 데 사용되므로, 데이터의 의미가 달라질 수 있어 주의가 필요합니다.
    // 특수한 경우 메모리의 특정 주소에 있는 값을 Device로 다루는 경우가 있을 수 있음
    // Device* p0 = reinterpret_cast<Device*>(0xabcd);
  • 이 부분은 주석 처리된 예제 코드입니다.
  • reinterpret_cast는 특정 메모리 주소를 특정 타입(Device*)으로 변환하여 다루고자 할 때 사용될 수 있습니다. 이는 하드웨어 장치의 메모리 주소에 직접 접근해야 하는 임베디드 시스템에서 사용될 수 있습니다. 예를 들어, 0xabcd라는 메모리 주소를 Device 타입 포인터로 다루고자 할 때 사용합니다.
  • 그러나 이런 방식은 위험할 수 있으며, 정확한 메모리 위치와 타입이 보장되는 경우에만 사용해야 합니다.
    // 0000,0000,0000,0000,0000,0000,0000,0001
    // int, 1의 비트 배열을 float 형태로 해석하면 float의 최소 값이 나옴
    int i = 1;
    float* a = reinterpret_cast<float*>(&i);
    cout << *a << endl;
    cout << FLT_TRUE_MIN << endl;
  • int i = 1;: i에 값 1을 할당합니다. 1은 메모리상에서 0000 0000 0000 0000 0000 0000 0000 0001로 저장됩니다.
  • float* a = reinterpret_cast<float*>(&i);: i의 주소를 float* 타입으로 변환합니다. 이제 a 포인터는 i의 메모리 데이터를 float로 해석하게 됩니다.
  • cout << *a << endl;: a가 가리키는 값을 float로 출력합니다. 1의 비트 패턴을 float로 해석하게 되는데, 이는 float의 가장 작은 양수 값에 해당합니다.
  • cout << FLT_TRUE_MIN << endl;: FLT_TRUE_MINfloat 타입에서 나타낼 수 있는 최소 양수 값을 출력합니다. 이는 이전 reinterpret_cast로 출력된 값과 같을 가능성이 높습니다.
    // 일반 형변환은 단순히 1이 나온다
    float b = i;
    cout << b << endl;
}
  • float b = i;: ifloat 타입으로 변환하여 b에 저장합니다. 일반적인 형 변환을 사용한 것이며, i의 값인 1float 타입으로 변환되어 b에 저장됩니다.
  • cout << b << endl;: b의 값을 출력합니다. 1float로 변환되었으므로 결과는 1.0으로 출력됩니다.

요약

  • 이 코드는 reinterpret_cast를 사용하여 메모리의 특정 주소를 다른 타입으로 해석하는 예제를 보여줍니다.
  • reinterpret_cast는 데이터의 의미를 바꾸지 않고 메모리 구조를 다른 타입으로 해석하는 용도로 사용되며, 위험성이 높아 주의가 필요합니다.
  • 이 예제에서는 int 타입의 메모리를 float로 해석하여 출력하거나, 특정 주소를 임의의 포인터 타입으로 변환하는 방식을 보여줍니다.
profile
李家네_공부방

0개의 댓글