티스토리 뷰

간혹 포인터의 주소 연산자 (&)를 이용하여 역참조 등을 할 일이 있다.

근데 절대 기억하지 못하는 특정 개체를 해제하지 않고 주소만으로 불러와야할 때도 있다.


어떤 값의 주소를 이용하여 역참조를 해보자.


Foo.h

class Foo {
public:
   Foo(const int value);
   ~Foo();
   int getValue();
private:
   int value;
};

우리가 잃어버릴 클래스다. value 변수는 생성자에서 설정한 value로 설정된다.


Testsuite.cc


#include <iostream>
#include <cstdint>
#include <sstream>
#include <string>

#include "Foo.h"

int main() {
   Foo foo(10);
   std::cout << &foo << std::endl;

   std::string dataAddress; {
      std::ostringstream ostream;
      ostream << reinterpret_cast<std::uintptr_t>(&foo);
      dataAddress = ostream.str();
   }

   std::cout << dataAddress << std::endl;

   std::uintptr_t p; {
      std::istringstream istream(dataAddress);
      istream >> p;
   }

   std::cout << p << std::endl;

   Foo *lost = (Foo *) reinterpret_cast(p);
   std::cout << lost->getValue() << std::endl;

   return 0;
};

굳이 std::string을 시용하여 주소를 저장해야하는지, 그건 필요에 따라 다를 것이다.

JNI와 같이 Java한테는 주소값을 넘겨줄만한 적당한 타입이 존재하지 않는다.

uintptr_t를 구현해서 Java에서 C++과 같이 주소를 저장하고 있다 다시 돌아와서 그 객체를 풀고 맞게 주소를 불러오기 보단

그냥 std::string <-> java.lang.String을 하는 것이 훨씬 나을 것이다.


하다못해 Java에서도 Unsafe 클래스를 이용하여 메모리 주소값으로 생성된 객체를 불러올 수 있는데

Native 언어로 그러지 못할리는 없을 것이다. 조금 불친절할 뿐이지.


추가1) 간혹 std::uintptr_t를 일반적인 primitive type으로 사용하는 방법에 대해서 묻는데, 이건 대상 플랫폼과 운영체제의 선언에 따라 다르다. 예를 들어 MSVC는 64비트에 unsigned __int64, 32비트에 unsigned int로 선언했고 GCC는 64비트에 unsigned long int, 32비트에 unsigned int로 선언되어있다. 필요에 따라 사용해야할 것이다.


추가2) 또한 이 기능 자체가 C++11부터 표준이 된 기능이다. 이전 표준에 대해서는 <cstdint>가 아닌<stdint.h>라는 C헤더를 이용해서 작성해야한다. 

'낙서' 카테고리의 다른 글

Java에는 포인터가 없다?  (0) 2017.10.19
C++ #pragma once  (0) 2017.10.19
C++ 포인터 주소값 저장하기  (0) 2017.10.12
C++ 동적할당의 고찰  (0) 2017.08.07
[HOWTO] Windows8 설치하기  (0) 2013.12.30
[HOWTO] 안드로이드에 우분투 설치하기  (0) 2013.12.30
댓글
댓글쓰기 폼