C++ 에서 null pointer 의 안전한 정수변환에 대해서 묻고 싶습니다.
글쓴이: winner / 작성시간: 금, 2012/02/10 - 4:55오후
C에서는 NULL 이 통상 ((void*) 0) 이기 때문에 걱정이 적습니다만 C++에서는 NULL 이 0 이기 때문에 형 인식과 관련해서 고민이 생깁니다.
저는 null pointer 를 implementation defined 에 의해 안정적으로 정수형으로 변환했다가 꺼내 쓰고 싶은데요.
이것이 API 에 의해서 정수형으로 전달되기 때문입니다.
예를 들어 API 에서 intptr_t 를 매개변수로 가진다면 C++ 에서는static_cast<void*>(0)
를 전달해야 하는 것인가요?
즉 trans_api(intptr_t param) 이라는 API 에 NULL ointer 를 전달할려면trans_api(reinterpret_cast<intptr_t>(static_cast<void*>(0)))
으로 해야 하나요?
어쩔 수 없는 면이 있습니다만 너무 불편하네요... -_-
사실 C 표준에서도 NULL 은 implementation-defined null pointer constant라고 서술만 했지 이것이 pointer 가 아닌 다른 형으로 변환될 때
null pointer 의 내부 표현을 지킬 수 있는지 의문이네요.
결국 C도
trans_api((intptr_t)(void*)0)
으로 해야 하는 건가요?
Forums:
해당 문제는 플랫폼에 따라 틀립니다. x86 이면
해당 문제는 플랫폼에 따라 틀립니다.
x86 이면 포인터 크기가 32bit 일거고 x86_64 이면 64bit 입니다.
사실 0이 바로 null pointer
사실 0이 바로 null pointer constant이기 때문에(C99에서조차도!) NULL을 굳이 ((void *)0)으로 정의할 필요는 없습니다. 그냥 0으로 정의하면 되지.
제 생각에 C에서 관습적으로 NULL을 그렇게 void *형으로 정의하는건 포인터가 아닌 곳에 잘못 사용되었을 시에
에러나 경고 메시지를 더 뽑아내고 싶어서가 아닌가 싶고요.
C++에서는 포인터의 형변환과 관련해서 좀 더 엄격하게 바뀌었기 때문에... (void *)0 처럼 NULL을 사용하지 못하고 그냥 0을 쓰는 거지요.
여기까지는 다 아시는 얘기일테고...
intptr_t면 그냥 정수형이죠? 정수형이면 그냥 0을 전달하면 될텐데 static_cast(0) 나 trans_api(reinterpret_cast(static_cast(0))) 와 같은 식으로 복잡하게 전달해야 할 이유를 잘 모르겠군요. 혹시 null pointer constant의 내부 표현이 모든 비트가 0이 아닐 경우를 고려해서 그러시는 거라면, 굳이 그럴 필요 없습니다. memcpy등으로 내부 비트를 그대로 복사하는 경우가 아니라면, 컴파일러가 알아서 해 주실 겁니다.
네. 굳이 그럴 필요없는 것을 고민해봤습니다.
reinterpret_cast 는 내부표현을 지키기 위해 존재합니다. static_cast 는 적절한 변환을 해주지요. 만일 null pointer 의 내부표현이 모든 bit 가 0 이 아니라면 static_cast 를 써야 올바른 내부표현을 가지는 null pointer 가 만들어집니다. 이 상황에서 reinterpret_cast 를 써야 올바른 내부표현을 보존하는 정수형을 얻을 수 있을테고요.
C와 C++가 섞여서 이야기되었고, 사실 저도 양쪽의 표준문서를 정확히 확인해보지는 않았는데 intptr_t 는 C99 에서 도입된 것으로 pointer 로부터 변환되었을 때 손실이 되지 않는 정수형으로 알고 있습니다.
사실 저는 Windows Programming 을 하고 있습니다. Windows message API 는 WPARAM과 LPARAM 두 개의 매개변수를 가질 수 있는데 이것은 각각 UINT_PTR 과 LONG_PTR 입니다.
Windows Programming 과 C, C++ 표준을 동시에 만족시킨다는 것은 과욕이긴 합니다만 한번 고민해보고 있습니다.
이번에 새로 나온 표준인 C++11에서
이번에 새로 나온 표준인 C++11에서 nullptr과 nullptr_t를 언어 차원에서 지원하는데요.
C++11을 이용할 수 있는 환경이 되시면 이것을 이용해보세요.
현재 gcc 4.6 이상에서 지원하구요. 윈도우즈에서는 VS 2010과 VS 2011에서 지원합니다.
[1] C++0x/C++11 Support in GCC
http://gcc.gnu.org/projects/cxx0x.html
[2] C++11 Features in Visual C++ 11
http://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx
——
———
Life is a tragedy when seen in close-up, but a comedy in long-shot. - Chaplin, Charlie -
Null pointer constant
C++11에서 지원하는 Null pointer constant에 대한 설명입니다.
http://en.wikipedia.org/wiki/C%2B%2B11#Null_pointer_constant
——
———
Life is a tragedy when seen in close-up, but a comedy in long-shot. - Chaplin, Charlie -
불행히도 전 VS 2003 을 쓰고 있습니다.
왜 그걸 쓰냐고 묻는다면 그냥 웃지요. ^_^
댓글 달기