NULL 문자가 헤더 파일에 정의 되어 있는 경우 같은 이름으로 재

skylandi의 이미지

iostream.h 파일에 NULL 문자가 define 되어 있는거 같은데요...
이거 사용 하지 않고 사용자가 직접 define NULL "\0"으로 지정 해서 사용 할수 있는 방법이 존재 하는 지 알고 싶습니다.

monpetit의 이미지

#ifdef NULL
#undef NULL
#define NULL "\0"
#endif

이정도면 무난하지 않을까요?
skylandi의 이미지

해결이 잘 되었습니다.

내가 하고자 하는길....

cinsk의 이미지

NULL과.. ASCII NUL 문자 '\0'은 다릅니다.

NULL은 0으로 표현되는 null pointer constant이고,

'\0'은 문자열 끝을 나타내는 문자 0이죠.

질문의 답은,

#ifndef NULL
#define NULL  ((void *)0)
#endif

가 맞습니다.

monpetit의 이미지

cinsk wrote:
질문의 답은,

#ifndef NULL
#define NULL  ((void *)0)
#endif

가 맞습니다.


NULL의 올바른 정의가 무엇인가 하는 것과 관계 없이, NULL을 "\0"으로 정의하고 싶은 경우가 아니었나요? :)
lsj0713의 이미지

원래의 질문 의도와는 다소 벗어난 글일 수도 있겠습니다만...

NULL을 0이나 '\'0' 이 아닌 "\0"로 재정의해서 쓰는 것은 별로 바람직하지 않습니다. "\0"은 ((void *)0) 이나 '\0' 과는 전혀 다른 뜻을 가지고 있으며 서로 같은 결과를 가지는 수식도 아닙니다. 만약 프로그램 중간에 널 포인터를 지시하기 위해 NULL 매크로 상수를 사용한 부분이 있다면, 큰 문제를 일으킬 수 있습니다. (이런 버그는 또한 발견하기도 어렵습니다)

굳이 "\0"을 사용할 필요가 있다면 NULL이 아닌 새로운 이름으로 만들어서 쓰기를 권합니다.

만약 "\0"이 아니라 '\0'이나 0 값을 가지게 한다면, 이것은 별 문제가 없습니다. '\0'이나 0이나 둘 다 int형 값을 가지며, void *형 포인터로 전혀 문제없이 변환되는 것이 보장됩니다. (단, C++에서는 '/0'이 char형 값을 가집니다. 이것이 포인터로 문제없이 형변환 될 수 있는지는 모르겠습니다. -_-;;)

참고로 C++에서는 (void *)형에서 다른 형의 포인터로 암시적인 형변환이 지원되지 않기 때문에, NULL은 ((void *)0)이 아니라 0으로 정의되어 있는 경우가 대부분입니다. 또한, 어떤 책에서는 NULL 대신에 그냥 0을 이용하라고 권하고 있기도 합니다.

그러나, NULL 매크로를 널 포인터가 들어갈 자리가 아닌 곳에 넣는 것은 별로 바람직한 습관이 아닙니다. (예를 들면 0인 숫자값 또는 문자와의 비교라던지...) NULL은 반드시 포인터가 들어갈 수 있는 자리에만 넣는 것이 바람직합니다.

saxboy의 이미지

Quote:

참고로 C++에서는 (void *)형에서 다른 형의 포인터로 암시적인 형변환이 지원되지 않기 때문에, NULL은 ((void *)0)이 아니라 0으로 정의되어 있는 경우가 대부분입니다. 또한, 어떤 책에서는 NULL 대신에 그냥 0을 이용하라고 권하고 있기도 합니다.

전에 저희 팀 프로젝트 하는데, 이렇게 쓰신 분이 계셔서 좀 당황했던 적이 있었지요. C기반이었거든요. :shock:

이런식이죠... 쩝

char *xx; 
xx= strdup("xxxx"); 
if ( xx==0 ) run_error(); 
cinsk의 이미지

질문이 C++ 이었군요. :)

#ifndef NULL
# ifdef __cplusplus
#  define NULL 0
# else
#  define NULL ((void *)0)
# endif
#endif /* NULL */
전웅의 이미지

monpetit wrote:
#ifdef NULL
#undef NULL
#define NULL "\0"
#endif

이정도면 무난하지 않을까요?

참고로 말씀드리면, #undef 는 일명 benign undefinition 을 지원해줍니다.
즉, #define 의 경우, 동일한 매크로 명이 이미 정의되어 있다면 특수한 조
건 (object-like 매크로의 경우, 치환 리스트가 토큰 대 토큰으로 동일해야
함) 을 만족해야 재정의가 허락되지만, #undef 의 경우 정의되어 있지 않은
매크로 명을 #undef 하는 것도 가능합니다. 따라서,

#undef NULL
#define NULL "\0"

라고만 해주셔도 동일한 효과를 얻을 수 있습니다. 물론, 표준 라이브러리
에서 예약하고 있는 명칭인 NULL 을 "예약된 문맥에서" 임의로 재정의하여
사용하는 것은 이식성이 보장되지 않는 행동입니다 - 이를 감수하고라도 그
와 같은 트릭을 써야 하는 상항이라면 별 수 없습니다만.

lsj0713 wrote:
NULL을 0이나 '\'0' 이 아닌 "\0"로 재정의해서 쓰는 것은 별로 바람직하지 않습니다. "\0"은 ((void *)0) 이나 '\0' 과는 전혀 다른 뜻을 가지고 있으며 서로 같은 결과를 가지는 수식도 아닙니다. 만약 프로그램 중간에 널 포인터를 지시하기 위해 NULL 매크로 상수를 사용한 부분이 있다면, 큰 문제를 일으킬 수 있습니다. (이런 버그는 또한 발견하기도 어렵습니다)

굳이 "\0"을 사용할 필요가 있다면 NULL이 아닌 새로운 이름으로 만들어서 쓰기를 권합니다.

전적으로 동의합니다.

단, 위와 같은 재정의가 "일반적인 경우" 표준 라이브러리에 정의되어 있는
매크로에는 영향을 주지 않습니다. 표준 라이브러리 구현은 다음과 같은 방
법이 (바람직하지는 않아도) 적법한 것이기에 매크로 정의에 NULL 을 사용
할 수 없습니다 - 대신 _NULL 같은 완전히 implementer 에게 예약된 명칭을
사용해야 합니다.

#include <stdio.h>
#undef NULL

int NULL = 0;    /* not good, but legal */

실제 표준 라이브러리를 구현하다보면, 현실적으로 거의 일어나지 않는 라
이브러리 사용자의 "적법한" 편법까지 고려하여 작성해야 하기에 골치 아픈
문제가 상당히 많습니다. 일례로,

#include <ctype.h>

int *pi = 0;

isprint(3.14);      /* #1 - legal */
(isprint)(3.14);    /* #2 - legal */

isprint(pi);        /* #3 - illegal */
(isprint)(pi);      /* #4 - illegal */

다수의 implementation 에서,

- #1 에서 진단 메시지가 발생하고, #2 에서는 진단 메시지가 발생하지 않
거나 (이 경우 #3, #4 모두에서 진단 메시지가 발생합니다)

- #1, #2 모두에서 진단 메시지가 발생하지 않는다면, #4 에서 진단 메시지
가 발생하고, #3 에서는 진단 메시지가 발생하지 않습니다.

이때, #1 에서 진단 메시지가 발생하며 그 이유로 프로그램의 번역이 실패
하는 경우, 혹은 #3 이 있음에도 아무런 진단 메시지를 보여주지 않는 경우
는 아주 사소한 이유로 표준을 따르지 않는 implementation 이 되어 버리는
경우입니다.

표준은 <ctype.h> 의 is*(), to*() 를 함수로 정의하면서 implementation
이 추가적으로 동일한 행동을 보이는 매크로로 제공할 수 있도록 허락하고
있지만, 매크로로 함수를 동일하게 흉내내는 것이 얼마나 어려운 지를 (심
지어는 아주 간단한 경우에도 불가능함을) 보여주는 예입니다.

lsj0713 wrote:
만약 "\0"이 아니라 '\0'이나 0 값을 가지게 한다면, 이것은 별 문제가 없습니다. '\0'이나 0이나 둘 다 int형 값을 가지며, void *형 포인터로 전혀 문제없이 변환되는 것이 보장됩니다. (단, C++에서는 '/0'이 char형 값을 가집니다. 이것이 포인터로 문제없이 형변환 될 수 있는지는 모르겠습니다. -_-;;)

데이터형은 문제가 되지 않습니다. 정수 상수 (integer constant) 는 (문자
형을 포함한) 모든 정수형을 포함합니다.

lsj0713 wrote:
참고로 C++에서는 (void *)형에서 다른 형의 포인터로 암시적인 형변환이 지원되지 않기 때문에, NULL은 ((void *)0)이 아니라 0으로 정의되어 있는 경우가 대부분입니다. 또한, 어떤 책에서는 NULL 대신에 그냥 0을 이용하라고 권하고 있기도 합니다.

"C 에서" (void *)0 의 데이터형은 엄밀히 이야기하면 void * 이지만, 다른
void * 형의 포인터 값과는 다른 특수성을 지닙니다 - (void *)0 를 0 값으
로 평가되는 다른 정수 상수 수식과 함께 특별히 null pointer constant 라
고 부르는 이유입니다. 예를 들어,

void *pv = 0;
void (*f)();

f = pv;           /* wrong */
f = (void *)0;    /* okay */

와 같은 모습을 확인할 수 있습니다 - "-ansi -pedantic" 같은 옵션을 사용
해 표준을 따르는 implementation 으로 번역해야 올바른 결과를 얻을 수 있
습니다.

saxboy wrote:
전에 저희 팀 프로젝트 하는데, 이렇게 쓰신 분이 계셔서 좀 당황했던 적이 있었지요. C기반이었거든요. :shock:

이런식이죠... 쩝

char *xx; 
xx= strdup("xxxx"); 
if ( xx==0 ) run_error(); 

흠... 익숙하지 않으셔서 당황하신 것 같습니다만, C 에서도 빈번히 사용되
는 형태입니다. 0 (혹은 0 의 값으로 평가되는 정수 상수 수식) 은 문맥에
따라 두가지 의미를 갖습니다 - 일반적인 정수 상수와 null pointer
constant 가 그것입니다. 위와 같은 포인터 문맥에서 0 은 null pointer
constant 의 의미를 갖고 xx 의 데이터형인 char * 형의 null pointer 로
변환되어 비교됩니다 - 따라서, 적법하고 (때때로 추천되는) 형태입니다.

cinsk wrote:
질문이 C++ 이었군요. :)

#ifndef NULL
# ifdef __cplusplus
#  define NULL 0
# else
#  define NULL ((void *)0)
# endif
#endif /* NULL */

이야기가 OP 의 최초 질문 의도에서 벗어나는듯 하지만, 앞서 말씀드렸듯이
C 에서도 0 은 null pointer constant 입니다. 따라서, C/C++ 을 모두 고려
하는 implementation 이라고 해도

#ifndef NULL
#    define NULL 0
#endif

만으로 충분합니다. 일부 implementation 에서 0 대신 ((void *)0) 나 0L
등을 사용하는 이유는 프로그래머가 NULL 을 잘못 사용하는 경우에도 의도
한 행동을 얻을 수 있도록 해주려는 일종의 "보너스" 입니다.

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.