if (p) 와 if (p != NULL) 중 어느 것을 선호하시나요?

hyde1004의 이미지

안녕하세요.

포인터 관련 코딩을 하다 보면, 종료를 확인하기 위해 NULL을 비교하는 구문이 많습니다.

예를 들면, 아래와 같은 경우입니다.

NULL이 '\0'과 동일하다는 가정하에서,
(1)과 (2), 그리고 (3)과 (4)는 동일한 구문일 것 같습니다.

이 때 개인적 선호에 따라서 (1), (3) 또는 (2), (4) 스타일 중 하나를 선택하게 되는 것일까요? (또는 관행적으로)
아니면 더 생각해봐야 하는 의미가 있을까요?

만약 두 개의 스타일이 동일한 결과를 보여준다면, 여러분들은 어떤 스타일을 더 선호하시나요?

if (p)                                       /* <-----  (1) -------> */
{
     /* chunk of code */
}
 
if ( p != NULL )                       /* <-----  (2) -------> */  
{
     /* chunk of code */
}
 
while ( p )                 /* <-----  (3) -------> */
{
    /* chunk of code */
}
 
while ( p != NULL)                 /* <-----  (4) -------> */
{
    /* chunk of code */
}

ymir의 이미지

p 가 pointer 나 boolean type 이라는 걸 직관적으로 쉽게 알아차릴 수 있는 경우에는 1,3 ..
type 을 쉽게 인지하기 어려운 경우에는 명시적으로 2,4 로 씁니다.
가급적 코드내에서 가독성을 잃지 않으면서, 나름대로 타이핑을 적게 하기 위한 방편..;;
그래서 되도록이면 1,3 으로 쓸 수 있도록 prototype 이나 logic 을 구성하려고 합니다.

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

declspec의 이미지

저도 코딩할때 저 문제로 고민해본적이 많아서
공감이 가네요

컴파일 할때 성능상의 차이가 있는지는 모르겠지만
가독성 면에서는 2, 4번이 좀더 좋은것 같아 정성스레 코딩할땐 2, 4번 스타일로
하죠 하지만 귀찮을땐 그냥 1, 3 처럼... -_-;;

자기실력이 좋다고 느껴지는건 공부를 안하고 있다는 신호.

세벌의 이미지

저는 간단한 걸 선호합니다.
가독성 중요 합니다만, 저 정도 코드는 아는 사람들은 다 아는 관습적으로 쓰이는 코딩 습관이라서 풀어쓸 필요를 못 느끼겠네요...

naveLcaro의 이미지

생각안해봤는데..
포인터일때는 if (p != NULL)로 하는데..
왜인지 Boolean은 if (isActivated) 라고 하네요;

..왜지;

----------------
Ubuntu 10.10, Solaris 11 / 잘 부탁드립니다 ;)

vacancy의 이미지


저도 이렇게 합니다.

익명 사용자의 이미지

변수의 경우
(1), (3)

함수의 경우
(2), (4)

를 선호합니다.
가령,

const char* sth = getSomething();
if( msg )
{
}

위와 같이 코드를 읽는사람이, if()를 결정하는 조건이 누구나 쉽게 알아보기 쉬운
포인터 타입의 변수이면 간략하게 쓰는것을 선호합니다.

if( getSomething() )
{
}

하지만 위 같이, (문법상) getSomething()의 리턴 타입이 포인터라는것을 알아보기 힘든경우에는
명시적으로 (2), (4)같이 풀어써줍니다.
getSomething()의 리턴이 int, long, bool 일지, pointer타입인지 명확하지가 않기때문입니다.

즉,
if() 괄호안의 코드만 보고도, 이게 포인터의 값을 비교하는지 명확한 경우에는( 비교 대상이 로컬 변수라던지, 아님 함수라도
malloc()이나 strdup() 같이 리턴타입이 너무 잘 알려진 함수라면 )
간략하게 씁니다만 - (1), (3),

그렇지 않은 경우에는( 주로 함수를 if()괄호안에 바로쓰는 경우들 ), (2), (4)를 선호합니다.

익명 사용자의 이미지

C/C++ 은 옛날 언어라서 이런게 좀 있죠... 일단 저는 보통 if (p != 0) 을 씁니다.

일단 if 나 while 같은건 논리적으로는 참/거짓만을 받아들여야 하겠죠. 단 C/C++ 은 if (x) 가 있으면 if (x != 0) 으로 암묵적으로 바꿉니다. 한편 0 은 비교 대상이 포인터이면 "null pointer" 로 고려됩니다. 즉 보통 컴파일러가 생각하는 순서는 if (p) => if (p != 0) => "0 을 null pointer 로 생각하고 pointer 가 null pointer 인지 체크" 의 순서죠.

한편 NULL 은 보통 macro 에 (#define 으로) 0 으로 정의되어 있습니다. 즉 전처리기가 NULL 을 모두 0 으로 바꿉니다. 즉 if (p != NULL) 은 if (p != 0) 으로 컴파일 전에 바뀌죠.

그래서 둘다 그럭저럭이긴 한데, 저는 if 나 while 같은 것은 논리 구문 (boolean predicate) 만을 받아들여야 한다고 생각하기 때문에 왠만하면 if (p != 0) 처럼 씁니다.

한편 0 을 암묵적으로 null pointer 로 해석하는 문제도 모호한 구석이 있기 때문에 뭐 C++0x 에서는 nullptr 을 도입하네 마네 했었는데 어찌 되었는지는 잘 모르겠습니다.

planetarium의 이미지

=> "0 을 null pointer 로 생각하고 pointer 가 null pointer 인지 체크"

이 부분이 이해가 안갑니다.
p != 0 이란 표현식을, p 에 값 0 이 들어있는지 확인하지 않고 또 변환을 거친다구요? 좀 괴상하게 들리네요. 근거가 있나요?

sblade의 이미지

3.2.2.3 Pointers

An integral constant expression with the value 0, or such an expression cast to type void * , is called a null pointer constant. If a null pointer constant is assigned to or compared for equality to a pointer, the constant is converted to a pointer of that type. Such a pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.

C standard 입니다.

엄밀한 의미에서 우리가 생각하는 숫자 0 과 "null pointer 상수"는 다른 거죠. 어쩌다 보니 C 에서 같은 기호를 쓰고 있을 뿐입니다. "null pointer 상수" 라 함은 "살아있는 pointer 와 비교하면 무조건 다른 것" 이지 숫자 0은 아니죠.

여하간 C 에서는 컴파일러가 p != 0 또는 p == 0 라는 표현을 보면 p 가 null pointer 인지 아닌지를 체크하게 되어 있습니다. 이걸 실제로 어떻게 하는지는 p 를 들여다보고 이것이 약속된 null pointer 패턴인지를 확인하는 겁니다. 이 약속된 null pointer 패턴은 그냥 0000... (zero bit pattern) 일수도 있고 따른 특정한 패턴일수도 있으며, 하드웨어마다 다릅니다 (그런데 대부분의 플랫폼이 zero bit pattern 이긴 합니다.)

planetarium의 이미지

좋은 답변 감사합니다.
전 null pointer가 0이 아닌 시스템이라면 NULL이 다른 값으로 define될거라고 생각했네요...
하긴 그런식이면 (!p) 같은 표현식은 못쓰겠죠.

익명 사용자의 이미지

(!p)로 NULL 포인터 체크하는 건 항상 안전합니다. NULL이 어떻게 정의되던지 간에..

C FAQ에 나와있는 내용이지요.

http://www.cinsk.org/cfaqs/html/node7.html

planetarium의 이미지

sblade님과 똑같은 설명의 반복 감사합니다만
제가 잠시 생각했던대로 "만약에" NULL이 다른 값으로 define 되는 식이라면 그럴수가 없을거라는 말씀 아닙니까.

planetarium의 이미지

한달넘게 지난 글입니다만 다시 읽다보니 궁금한게 생겼습니다.
An integral constant expression with the value 0, 생략, is called a null pointer constant.

결국 기계어 레벨에서 null pointer constant가 all-zero bit이 아닐수 있더라도,
C언어 레벨에서 null pointer constant는 항상 0이라고 생각해도 되는건가요?

planetarium의 이미지

아니군요,
ISO/IEC 9899:1999 의
7.17절 Common definitions
항목의 3항에 The macros are NULL which expands to an implementation-defined null pointer constant
라는 말이 있습니다.

그럼
void *p = NULL; 이고 int a = NULL; 일때
p == a; --> 참
p == 0; --> 참
a == 0; --> 거짓
이란 말인가요?!? 으아...

익명 사용자의 이미지

if ( ptr ) 같은 것은 너무 관용적으로 널리 쓰이는 스타일이기 때문에
굳이 if ( ptr != NULL ) 처럼 쓸 필요는 없다고 생각합니다.
이건 제대로 못 읽는 사람이 문제입니다.

위에 어떤 분이 지적하신 if ( func() ) 와 같은 상황에서도
굳이 등호를 쓸 필요는 없어 보입니다.
이런 상황에서는 등호의 유무 보다는 func()의 함수 이름이 더 중요하지 않을까요.
아니면 차라리 주석을 달던가.

참고로 if문의 정의는 다음과 같습니다.

if ( expression ) statement
if ( expression ) statement else statement

In both forms, the first substatement is executed if the expression compares unequal to 0.

원래 if문의 정의 자체에 0과의 비교라는 의미가 들어가므로, != 0 또는 == 0 이라는 수식은 불필요합니다.

익명 사용자의 이미지

저는 포인터인 경우와 그렇지 않은경우를 나눠서 쓰네요

그리고 NULL과 '\0' 는 다른데 왜 동일하다는 가정을 썻나요?

emptynote의 이미지

java는 2번, 4번 처럼 많이 사용하는데요.

지금은 조엘온소프트웨어 책에서 조엘이 알려준 if (null != p) 방식을 사용할려고 노력중입니다.

if문 조건으로 != 으로 사용할지 == 으로 사용할지는

코드 리뷰할때 마다 달라지기에 c or c++ 할때에도 2번, 4번 방식을 기계적으로 하게 됩니다.

poplinux의 이미지

저는 무조건 2, 4

========================
조직 : E.L.D(Embedded Linux Developer/Designer)
블로그 : poplinux@tistory.com
카페 : cafe.naver.com/poplinux

임베디드 리눅스 관련 프리렌서 지향

익명 사용자의 이미지

무조건 풀어씁니다!

익명 사용자의 이미지

엄격한 컴파일러를 쓰고, warning을 모두 체크하다보면 2,4처럼 해주는 편이 편합니다. 물론 첫 코딩 때야 아무런 메시지 없이 넘어갈지는 모르지만 이런저런 사람들이 수정에 수정을 거듭하다보면 어쩌다가 타입이 바뀌면 워닝 메시지라도 날려주거든요. 그럼 누가 코딩 법칙을 어겼는지 알 수 있죠 :-)

댓글 달기

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