C++ 에서 null pointer 의 안전한 정수변환에 대해서 묻고 싶습니다.

winner의 이미지

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)
으로 해야 하는 건가요?

익명 사용자의 이미지

해당 문제는 플랫폼에 따라 틀립니다.

x86 이면 포인터 크기가 32bit 일거고 x86_64 이면 64bit 입니다.

익명 사용자의 이미지

사실 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++ 표준을 동시에 만족시킨다는 것은 과욕이긴 합니다만 한번 고민해보고 있습니다.

empty2fill의 이미지

이번에 새로 나온 표준인 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 -

empty2fill의 이미지

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 -

익명 사용자의 이미지

왜 그걸 쓰냐고 묻는다면 그냥 웃지요. ^_^

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.