소스코드에서 NULL을 사용할때..

superkkt의 이미지

char *cp;

cp = strrchr( argv[0], '/' );
if ( cp != (char*) 0 )
	++cp;
else
        --cp;

if( cp != NULL) 이렇게 하는게 가독성이 더 좋지 않나요? 굳이 위와 같이 사용하는 이유가 있습니까?

File attachments: 
첨부파일 크기
Image icon Screenshot-Emacs-CWarn-Mode.png14.57 KB
addnull의 이미지

음.. 제가 알기론 저런 식으로 직접적인 값을 쓰는게 더 안좋다고 알고 있습니다.

언제나
NULL == 0
EOF == -1
라고 보장될 수 없기에..

2005년 11월 4일.

doldori의 이미지

어니스트 wrote:
언제나
NULL == 0
라고 보장될 수 없기에..

이것은 보장됩니다. 정수형 상수 0은 정수 0을 나타내기도 하지만 null pointer
constant라는 의미를 갖고 있기도 합니다.

http://bbs.kldp.org/viewtopic.php?p=77060&highlight=#77060

시간 나실 때 전웅님의 글을 찾아서 읽어보십시오. 재밌는 거 많습니다.

cinsk의 이미지

if (cp != NULL) ...

if (cp != (char*)0)  ...

if (cp != 0) ...

if (cp) ...

다 같습니다.
addnull의 이미지

전웅 wrote:
0 은 정수 상수인 동시에 null pointer constant 라는 독특한 역할을 갖고
있습니다. 즉, 0 값을 갖는 정수 상수 수식이나, (void *) 로 변환되는 0
값을 갖는 정수 상수 수식은 포인터가 관련된 문맥에서 null pointer 로 변
환된다고 정의되어 있는 것입니다.

음.. 그렇군요.
내부적으로 "null pointer != 0" 아닌 machine에서도
포인터 관련한 수식에서 0은 해당 machine에 정의된 null pointer로 변환된다는 거군요.

즉,
0, NULL, ((void*)0), null pointer constant
끼리는 서로 항상 같음이 보장되어있고,
null pointer는 machine에 따라 달라질 수도 있다.라고 이해했습니다.

혹시 잘못 이해한 점이 있으면 다시 한번.. ^^;

lifthrasiir의 이미지

어니스트 wrote:
음.. 제가 알기론 저런 식으로 직접적인 값을 쓰는게 더 안좋다고 알고 있습니다.

언제나
NULL == 0
EOF == -1
라고 보장될 수 없기에..

2005년 11월 4일.

EOF도 항상 -1인 것은 아닙니다. EOF는 int 형이면서 음수를 나타내기만 하면 됩니다(C99에 따르면). -1이 많이 쓰이긴 하지만요.

- 토끼군

ohhara의 이미지

superkkt wrote:
char *cp;

cp = strrchr( argv[0], '/' );
if ( cp != (char*) 0 )
	++cp;
else
        --cp;

if( cp != NULL) 이렇게 하는게 가독성이 더 좋지 않나요? 굳이 위와 같이 사용하는 이유가 있습니까?

여러가지 이유가 있을 수 있겟지만...
좀 후진 시스템에서는 NULL이 define되어 있지 않아서 NULL을 사용하면 undefined error가 발생하고 0을 쓰면 error가 발생하지 않아서 그럴 수 있습니다. 그렇다고 소스마다 NULL을 define해 주면 어떤 시스템에 옮겼을 때 multiple defined error가 발생하기도 하고 그렇다고 해서 ifndef로 묶어주면 아마 macro가 아닌 global variable로 NULL이 정의되어 있는 시스템이라면 또 다른 문제가 발생할 가능성이 있습니다.

저런 이유로 NULL보다 0을 쓰는게 속편한 경우가 가끔 있습니다. -_-;

Taeho Oh ( ohhara@postech.edu ) http://ohhara.sarang.net
Postech ( Pohang University of Science and Technology ) http://www.postech.edu
Alticast Corp. http://www.alticast.com

익명 사용자의 이미지

참고로 C++에서는 C와는 달리 void*형으로부터 다른 포인터 형으로의 암시적인 형변환이 지원되지 않기 때문에, NULL은 그냥 0으로 정의되어 있으며

if ( cp != (char*) 0 )

는 cp의 타입이 char *가 아닌 경우에는 경고나 에러메시지를 발생시킵니다.

제가 짠다면

if ( cp )

로 하겠습니다. 짧고, 간단하며 명확합니다(null pointer와 if의 동작에 익숙한 프로그래머에게는).

익명 사용자의 이미지

Quote:
if ( cp != (char*) 0 )

저는 이 스타일을 즐겨 사용합니다.
이유는? 없습니다. 그냥 ......
가끔, (void) printf(.....); 이렇게도 씁니다.
이유는 모릅니다. :twisted:
jam02의 이미지

Anonymous wrote:
참고로 C++에서는 C와는 달리 void*형으로부터 다른 포인터 형으로의 암시적인 형변환이 지원되지 않기 때문에, NULL은 그냥 0으로 정의되어 있으며

if ( cp != (char*) 0 )

는 cp의 타입이 char *가 아닌 경우에는 경고나 에러메시지를 발생시킵니다.

제가 짠다면

if ( cp )

로 하겠습니다. 짧고, 간단하며 명확합니다(null pointer와 if의 동작에 익숙한 프로그래머에게는).

저도 이렇게 할 것 같네요.
물론 C++에서의 문제 때문입니다.

pynoos의 이미지

C와 C++을 코드를 작성할 때, 자신이 C 프로그램을 작성하는지 C++프로그램을 작성하는지를 알 것이고, 정확히는 작성하는 코드를 C 컴파일러에게 던질 것인지, C++ 컴파일러에게 던질 것인지를 알것이므로, 두 상황에서 NULL 이나 0 을 각각 쓰면 됩니다.
(void *) 캐스팅도 마찬가지 입니다만, 될 수 있으면, C와 C++의 문맥에 맞게 사용하면 됩니다.

저도 첨엔 분리가 잘 안되다가 요즘엔 잘 되더군요. :)

moonzoo의 이미지

0이나 (void *)0을 쓸 필요가 있나여?

저는 NULL을 선호합니다.

NULL에는 Null pointer를 가리키는 적절한 추상화가 되어있지만

포인터 연산에 0이라고 써놓고, 이것은 Null Pointer였지!

라고 생각하는것은 별로가 아닐까요?

pynoos의 이미지

moonzoo wrote:

포인터 연산에 0이라고 써놓고, 이것은 Null Pointer였지!

라고 생각하는것은 별로가 아닐까요?

이것은 관례가 아니라 언어에서 그렇게 취급하는 것이 명세에 들어있어서 일 것입니다.

keizie의 이미지

wiki:ZeroAsNull 입니다. 부족하거나 틀린 부분이 있으면 고쳐주세요.

쌀밥의 이미지

주제와는 다르지만 참고가 될까 하고 적어봅니다.

if ( cp != (char*) 0 )
라고 적는 것 보다는

if ( (char*) 0 != cp )
라고 적는 것이 실수를 줄일 수 있습니다.

종종 == 를 = 로 써버리는 실수를 해서 (사소한) 버그로 고생할때가 있는데
좌우를 바꿔 놓으면 이런 실수를 미연에 방지할 수 있지요...

처음에는 이런식으로 사용하는게 잘 안읽혀서 불편했는데
얼마 안가서 익숙해지더군요.
그리고 이 덕분에 버그 몇개를 예방한 경험도 있어서 애용하게 되었습니다.

일하는 사람들의 희망 민주노동당 : http://www.kdlp.org
반공 교육의 성과로, 민주주의의 반대가 공산주의(또는 사회주의)라고 생각하는 사람이 많다.

addnull의 이미지

쌀밥 wrote:
주제와는 다르지만 참고가 될까 하고 적어봅니다.

if ( cp != (char*) 0 )
라고 적는 것 보다는

if ( (char*) 0 != cp )
라고 적는 것이 실수를 줄일 수 있습니다.

종종 == 를 = 로 써버리는 실수를 해서 (사소한) 버그로 고생할때가 있는데
좌우를 바꿔 놓으면 이런 실수를 미연에 방지할 수 있지요...

C#이나 Java에선 언어 자체적으로
if 문 안에서 = 연산자를 못쓰게 하더군요.

이렇게 강제하는게 좋은건지는 아직 잘 모르겠습니다.. =_=)a?

2006년 1월 17일.

ssehoony의 이미지

쌀밥 wrote:
if ( (char*) 0 != cp )
라고 적는 것이 실수를 줄일 수 있습니다.

이런 문제로 고생해보신 경험이 다들 한번 정도 있을 법한데
요즘 유명한 컴파일러들은 if 에 assign 이 들어가면 경고를 해주는 센스를 보여주지요.

어니스트 wrote:
C#이나 Java에선 언어 자체적으로
if 문 안에서 = 연산자를 못쓰게 하더군요.

이렇게 강제하는게 좋은건지는 아직 잘 모르겠습니다.. =_=)a?


if 안에 assign 을 사용하는게 runtime 입장에서 효율적인 경우는 없는 듯 합니다.
(소스코드 라인수가 줄어드는 것 말고는 특징이 없는 듯 합니다. 가독성은 떨어지고)
그런 의미에서 인재를 막을 수 있는 제약 사항은 좋다는게 개인적 견해입니다.
죠커의 이미지

kz wrote:
wiki:ZeroAsNull 입니다. 부족하거나 틀린 부분이 있으면 고쳐주세요.

kz님의 위키에서 한참 찾았습니다. OTL. 거기에 있었군요.

cinsk의 이미지

ssehoony wrote:
쌀밥 wrote:
if ( (char*) 0 != cp )
라고 적는 것이 실수를 줄일 수 있습니다.

이런 문제로 고생해보신 경험이 다들 한번 정도 있을 법한데
요즘 유명한 컴파일러들은 if 에 assign 이 들어가면 경고를 해주는 센스를 보여주지요.

유명한 editor의 경우, 그런 문장을 발견하면 bold체나 다른 색상으로 해당 assignment operator를 보여주기도 합니다. :wink: 첨부 파일은 Emacs에서 cwarn-mode를 on한 상태입니다. 참고하세요.

Quote:

if 안에 assign 을 사용하는게 runtime 입장에서 효율적인 경우는 없는 듯 합니다.
(소스코드 라인수가 줄어드는 것 말고는 특징이 없는 듯 합니다. 가독성은 떨어지고)
그런 의미에서 인재를 막을 수 있는 제약 사항은 좋다는게 개인적 견해입니다.

개인적으로, 가독성이라는 말 크게 중요하게 생각하지 않습니다. 수치로 확실히 나오는 것도 아니고, 또 취향에 따라 한 사람에게 쉽게 읽혀지는 코드가, 다른 사람에게는 그렇지 않기 때문입니다. 다음과 같은 코드를 보면:

FILE *fp;
if ((fp = fopen(pathname, "r")) != NULL)
  do_something;

물론 취향에 따라 다르겠지만, 위와 같은 코드가 여러 줄 있다고 치면, 전체적으로 코드의 길이가 줄어들어, 한번에 코드의 흐름을 이해하는데 도움을 줄 수도 있습니다.

즉, 무엇이 가독성을 높여 주는지는 관점에 따라 다르다는 말이지요.

또한 이런 assignment를 언어 차원에서 제한하는 것은 그리 바람직하지 않다고 생각합니다. 차라리 말씀하신 것처럼 컴파일러 경고로 보여준다거나 하는 등, 웬만하면 자유를 주는 것이 더 낫다고 생각합니다.

댓글 첨부 파일: 
첨부파일 크기
Image icon 0바이트
익명 사용자의 이미지

cinsk wrote:

...
웬만하면 자유를 주는 것이 더 낫다
...

공감!

doldori의 이미지

어니스트 wrote:
C#이나 Java에선 언어 자체적으로
if 문 안에서 = 연산자를 못쓰게 하더군요.

그렇다면 = 연산의 의미가 C와는 다르겠군요. C에서는
  • 수식 내에 = 연산이 사용될 수 있으며 수식의 값은 좌변의 값으로 평가된다.
  • 0은 false, 0이 아닌 값은 true이다.
라는 것에 의해 조건문에서 쓰일 수 있습니다. C#이나 Java가 조건문에서 = 연산을 허용하지 않는 것은 문법적으로 어떻게
설명되나요?[/]
creativeidler의 이미지

Quote:
C#이나 Java가 조건문에서 = 연산을 허용하지 않는 것은 문법적으로 어떻게
설명되나요?

문법적으로 허용되지 않는 것을 설명할 필요는 없죠. 그냥 문법적으로 지원되지 않는다가 정답입니다.

그렇지만 굳이 설명한다면 C에서는 statement도 expression이고 조건문 안에는 expression이 들어갈 수 있지만 Java에서는 조건문 안에는 boolean expression만 들어갈 수 있고 statement는 expression이 되지 않는다라고 말할 수는 있겠죠.

doldori의 이미지

creativeidler wrote:
Quote:
C#이나 Java가 조건문에서 = 연산을 허용하지 않는 것은 문법적으로 어떻게
설명되나요?

문법적으로 허용되지 않는 것을 설명할 필요는 없죠. 그냥 문법적으로 지원되지 않는다가 정답입니다.

그렇지만 굳이 설명한다면 C에서는 statement도 expression이고 조건문 안에는 expression이 들어갈 수 있지만 Java에서는 조건문 안에는 boolean expression만 들어갈 수 있고 statement는 expression이 되지 않는다라고 말할 수는 있겠죠.


결국 = 연산의 결과는 boolean 수식이 아니기 때문이라는 것이군요.

ps. C에서도 문장과 수식은 다릅니다.

익명 사용자의 이미지

C++에서 NULL을 쓰는 것보다 0을 쓰는것이
문제가 적다고 합니다
C에서 NULL이 매크로로 정의되어 있어서 문제가 발생할 소지가 있습니다.
혹시 다른곳이서 NULL을 재정의하거나 하는....
굳이 NULL을 쓰고 싶으면 const int NULL = 0;
이라고 정의해서 사용하는 것이 좋습니다.

kfmes의 이미지

아시는 분은 아시겠지만
java에서

무한루프돌릴때
while(1)
도 안됩니다
while(true)
이런식으로 돌려야 하지요

조건식 결과가 boolean 형이 아니면
에러를 뱉습니다 -_ -

----------------------------------------

죠커의 이미지

Anonymous wrote:
C++에서 NULL을 쓰는 것보다 0을 쓰는것이
문제가 적다고 합니다
C에서 NULL이 매크로로 정의되어 있어서 문제가 발생할 소지가 있습니다.
혹시 다른곳이서 NULL을 재정의하거나 하는....
굳이 NULL을 쓰고 싶으면 const int NULL = 0;
이라고 정의해서 사용하는 것이 좋습니다.

단순한 상수로서 사용되는 부분에서 그다지 문제될 부분은 없다고 생각합니다.

그리고 여담이지만 일부 사람들이 제기하는 디버깅이 힘들다는 것 역시 현대적인 환경에서는 안 맞는 말이 아닌가 합니다.

doldori의 이미지

저도 NULL보다는 0을 선호하긴 합니다만...

Anonymous wrote:
혹시 다른곳이서 NULL을 재정의하거나 하는....
굳이 NULL을 쓰고 싶으면 const int NULL = 0;
이라고 정의해서 사용하는 것이 좋습니다.

C나 C++이나 이 방법을 쓰려면 먼저 NULL을 #undef 해야 하는 것은 당연하고...

C라면 이 방법은 좋지 않습니다. 이렇게 하면 NULL을 포인터에 대입할 때
int --> 포인터형의 변환이 이루어져야 하는데, 암시적 변환은 허용하지 않으므로
캐스트를 써야 합니다. 그리고 변환된 결과는 구현체 의존적이라서 이식성도 없습니다.
C++에서는 이렇게 선언된 NULL을 상수 수식으로 취급하기 때문에 이 방법이 가능하기는 합니다.

이런 방법이 나오게 된 원인이 NULL이 매크로이기 때문인데, 사실 매크로 앞에서는
별로 뾰족한 수 없습니다. NULL 뿐만 아니라 매번 그 많은 매크로를 #undef하는
것도 비현실적이고요. "혹시 다른곳이서 NULL을 (다른 의미로) 재정의하거나 하는"
경우를 당한다면 뭐, 어쩌겠습니까. 욕이나 퍼부어주는 수밖에요.

krisna의 이미지

보통의 경우에 직접 NULL 상수를 재정의 해서 프로그램하는 경우는 적은 것 같은데요.

GCC의 경우 C에서는 ((void *)0) (사실은 __null 이더군요) 으로 치환되고 C++에서는 0으로 치환되어서 프로그래머가 굳이 NULL대신 0을 쓰지 않아도 0으로 치환되는 것으로 알고 있습니다.

참조 GCC의 stddef.h

#ifdef __GNUG__
#define NULL __null
#else   /* G++ */
#ifndef __cplusplus
#define NULL ((void *)0)
#else   /* C++ */
#define NULL 0
#endif  /* C++ */
#endif  /* G++ */

그래서 제 경우는 오히려 문맥 정보가 뚜렷한 NULL을 사용하고 있습니다.
다른 컴파일러들의 경우 C와 C++에 따른 NULL 매크로를 제공해 주지 않습니까?

댓글 달기

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