헤더파일 이해하기 --??

ktlsu1231의 이미지

Quote:

#ifndef __errors_h
#define __errors_h
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef DEBUG
#define DPRINTF(arg) printf arg
#else
#define DPRINTF(arg)
#endif

#define err_abort(code, text) do{\
fprintf(stderr, "%s at \"%s\":%d: %s\n", \
text, __FILE__, __LINE__, strerror (code));\
abort();\
}while(0)

#define errno_abort(text) do {\
fprintf(stderr, "%s at \"%s\":%d: %s\n", \
text, __FILE__, __LINE__, strerror(errno));\
abort();\
} while(0)

#endif

안녕하세요.
Header 파일입니다.
저는 __FILE__, __LINE__ 이런 서식과
#ifndef __errors_h
#define __errors_h
#ifdef DEBUG
#define DPRINTF(arg) printf arg
#else
#define DPRINTF(arg)
#endif
이런 표현들이(매크로?--?) 생소합니다.
아무리 봐도 겁만나네요. t_t

이런 것을 이해하려면 어떻게 해야하죠?
별 내용은 없는 것 같은데, 무엇을 보아야 할지 모르겠습니다.

\ 이것은 한줄을 여러줄러 나누어사용하려고 사용한 것이죠?

lacovnk의 이미지

#ifdef 등등은 프리프로세서로 검색하시며 될듯 합니다

컴파일 이전에, 치환 비스무리하게 처리해주는 것입니다.

그리.. __BLABLA__ 이런건 아마 어딘가에 있는 매크로일껍니다 :)

ㅡ,.ㅡ;;의 이미지

디파인의 용도를 아신다면..
이것자체가 매크로함수의 좋은예제이네요..ㅡ,.ㅡ;;

__FILE__, __LINE__
이건 아마도 전역변수겠지요. 선언을 찾아보시면 알겠죠.
#ifndef __errors_h
#define __errors_h
#ifdef DEBUG
#define DPRINTF(arg) printf arg
#else
#define DPRINTF(arg)
#endif

__errors_h
이런것모두 그냥 이름을 저렇게 지었을뿐입니다.
아마도 이소스의 이름은 errors.h 이겠지만요..

한가지 do while 문에서 0을준건
매크로내부함수들을 묶어두려는 의도로보이는데..
꼭저렇게 했어야하는지 의문..


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

yui의 이미지

ktlsu1231님. C책에서 전처리기, 전처리기 지시자(?) 항목을 찾아보세요.

그리고 예로 드신 것들은 굉장히 자주쓰이는 거라 쓰임을 간단히 적어봅니다.

1) header파일 wall
#ifndef something_h
#def something_h
.. 실제 내용
#endif
실제 내용안에 클래스 정의등이 있으면 한 번역단위내에서 이 헤더파일이 두번 include되는 경우, 정의가 두번되었다고 컴파일 에러가 발생합니다.
위의 방어벽을 쌓아놓으면 이런 문제가 생기지 않습니다. 두번째로 include하려고 하면 이미 something_h가 정의되어 있기 때문에 #endif까지의 내용을 건너뛰게 됩니다.

2) DEBUG
전 잘 안씁니다만, 만약 DEBUG라는게 정의되어 있으면 DPRINTF를 printf로 바꿔써주게 됩니다. 그럼 printf이 실행되어 디버그 메세지가 출력되겠죠. 정의되어 잇지 않으면 당연히 출력되지 않습니다.

2) __FILE__, __LINE__
이것은 현재 파일과 라인 이름으로 치환됩니다. 에러메세지 출력할 때 좋겠죠? __FUNC__ 이나 gcc 확장으로 더 좋은 몇개 이름이 있으니 찾아보세요.

3) do while
define으로 매크로 함수를 작성하는 경우 do while로 감싸는 테크닉이 없이 그냥 정의하면 컴파일 에러가 나는 경우가 있습니다. 이를 방지하기 위해 저렇게 열심히 do while(0)로 감싸주죠. 의미는 똑같습니다.

ㅡ,.ㅡ;; wrote:
디파인의 용도를 아신다면..
이것자체가 매크로함수의 좋은예제이네요..ㅡ,.ㅡ;;

__FILE__, __LINE__
이건 아마도 전역변수겠지요. 선언을 찾아보시면 알겠죠.
#ifndef __errors_h
#define __errors_h
#ifdef DEBUG
#define DPRINTF(arg) printf arg
#else
#define DPRINTF(arg)
#endif

__errors_h
이런것모두 그냥 이름을 저렇게 지었을뿐입니다.
아마도 이소스의 이름은 errors.h 이겠지만요..

한가지 do while 문에서 0을준건
매크로내부함수들을 묶어두려는 의도로보이는데..
꼭저렇게 했어야하는지 의문..

opt의 이미지

ANSI 표준인지는 제가 최근 표준을 지속적으로 따라가고 있지 않기 때문에 잘 모르겠고.... 실용적 차원에서 답변을 드리겠습니다.

__FILE__ : 대부분의 컴파일러에서 현재 파일명을 나타냅니다.
__LINE__ : 대부분의 컴파일러에서 현재 행을 나타냅니다.

위 둘 다 흔히 에러 처리시 에러가 발생한 모듈(파일)과 라인 위치를 나타내기 위해 쓰입니다(헤더 파일들을 grep 으로 뒤져보시면 나올 듯).

#ifndef __errors_h
#define __errors_h
는 특정 헤더 파일이 컴파일 과정에서 중복적으로 include 되지 않도록 하는 것으로 #include <foo.h> 가 실제 컴파일시 foo.c 내부에서 치환된다는 것을 생각해보면, 컴파일 속도 저하를 막기 위해 중복 include 를 막는 것임을 알 수 있습니다.

errno_abort 식의 함수 매크로는 매우 잘 사용되는 패턴이니 꼭 익혀두세요.
do { } while(0) 도 매우 자주 사용됩니다.

자세한 정보는 http://man.phpschool.com/manual/kr/control-structures.do.while.php 를 참조하세요.

C 고급 코딩 기법이.... php 사이트에 있다는게 잼나네요.
보다 자세한 사항은 han 그룹의 과거 포스팅들 뒤져보시면.... 나올듯....

http://www.geocrawler.com/mail/msg.php3?msg_id=1976242&list=357 도 좋은 답변인 듯....

----
LUX ET VERITAS | Just for Fun!

ㅡ,.ㅡ;;의 이미지

yui wrote:

3) do while
define으로 매크로 함수를 작성하는 경우 do while로 감싸는 테크닉이 없이 그냥 정의하면 컴파일 에러가 나는 경우가 있습니다. 이를 방지하기 위해 저렇게 열심히 do while(0)로 감싸주죠. 의미는 똑같습니다.

#define err_abort(code, text) do{\ 
fprintf(stderr, "%s at \"%s\":%d: %s\n", \ 
text, __FILE__, __LINE__, strerror (code));\ 
abort();\ 
}while(0) 

제가하는방식은
#define err_abort(code, text) (\
fprintf(stderr, "%s at \"%s\":%d: %s\n", \
text, __FILE__, __LINE__, strerror (code)),\
abort()\
)
입니다.

위에것은 정상이고 아랫것이 비정상적으로 먹히는경우가 어떤경우가 있지요?
더구나 제가하는방식은 return 조차 받아낼수 있다는장점이있어 대부분 저렇게 사용하는데요.


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

cdpark의 이미지

ㅡ,.ㅡ;; wrote:
제가하는방식은
#define err_abort(code, text) (\
fprintf(stderr, "%s at \"%s\":%d: %s\n", \
text, __FILE__, __LINE__, strerror (code)),\
abort()\
)
입니다.

위에것은 정상이고 아랫것이 비정상적으로 먹히는경우가 어떤경우가 있지요?
더구나 제가하는방식은 return 조차 받아낼수 있다는장점이있어 대부분 저렇게 사용하는데요.

서로 일장일단이 있습니다. 괄호와 컴마연산자를 쓰는 경우, 그 안에 for나 while 문을 넣을 수 없습니다. 또한 변수 선언도 불가능하죠. 대신 값을 돌려받을 수 있고요. do{ ... } while(0)는 반대죠.

gcc 확장을 이야기한다면 무효~ :roll:

ㅡ,.ㅡ;;의 이미지

cdpark wrote:
ㅡ,.ㅡ;; wrote:
제가하는방식은
#define err_abort(code, text) (\
fprintf(stderr, "%s at \"%s\":%d: %s\n", \
text, __FILE__, __LINE__, strerror (code)),\
abort()\
)
입니다.

위에것은 정상이고 아랫것이 비정상적으로 먹히는경우가 어떤경우가 있지요?
더구나 제가하는방식은 return 조차 받아낼수 있다는장점이있어 대부분 저렇게 사용하는데요.

서로 일장일단이 있습니다. 괄호와 컴마연산자를 쓰는 경우, 그 안에 for나 while 문을 넣을 수 없습니다. 또한 변수 선언도 불가능하죠. 대신 값을 돌려받을 수 있고요. do{ ... } while(0)는 반대죠.

gcc 확장을 이야기한다면 무효~ :roll:

그야 사용하는것이 틀린데 그에 맞게 하죠
제말은 위와같은경우 왜저렇게 했나 하는겁니다.

이러저러한경우는 if 보다 switch 문이 낮지 않은가 라고 했는데 다른경우는 if도 장점이 있다고 말하는건 이상하죠..if를 써야할곳에는 써야되니까요..

더구나 아무리 그렇다하더라도 제게 어째서 테크닉이 되는지 이해 못하겠군요..
저런식은 어떤인자로 사용도 못합니다. 아주 불합리하지 않나요?

내부에서 변수선언과 루프를 돌리고 싶으면 ({ 를 중첩사용하면 아주잘되는데
왜저렇게하나요..


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

Testors의 이미지

ㅡ,.ㅡ;; wrote:

그야 사용하는것이 틀린데 그에 맞게 하죠
제말은 위와같은경우 왜저렇게 했나 하는겁니다.

이러저러한경우는 if 보다 switch 문이 낮지 않은가 라고 했는데 다른경우는 if도 장점이 있다고 말하는건 이상하죠..if를 써야할곳에는 써야되니까요..

더구나 아무리 그렇다하더라도 제게 어째서 테크닉이 되는지 이해 못하겠군요..
저런식은 어떤인자로 사용도 못합니다. 아주 불합리하지 않나요?

위 예에서는 abort() 를 하기때문에 다른 인자로 쓸 필요가 없습니다.
리턴값도 받을 필요가 없구요..
그렇다고 안에서 변수선언이나 루프도 돌지 않습니다.
결론은 뭘 쓰든 동작이나 퍼포먼스와는 관계가 없고,
제가 보기에는 다만 스타일 문제로 보입니다.

ㅡ,.ㅡ;; wrote:
내부에서 변수선언과 루프를 돌리고 싶으면 ({ 를 중첩사용하면 아주잘되는데
왜저렇게하나요..

아주 잘 되나요? 제 VC .net 에서는 안됩니다.
그런데 cdpark 님께서 이미 "gcc 확장을 이야기한다면 무효~" 라고 하신듯 한데요~ :P

http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html#Statement%20Exprs

ㅡ,.ㅡ;;의 이미지

Testors wrote:

위 예에서는 abort() 를 하기때문에 다른 인자로 쓸 필요가 없습니다.

예를 하나들어보죠..

if( x > (( y )? y : err_abort( code, text ))) z = x / y;

이런경우 안된다는겁니다. 물론여기서는 함수 인자는아니지만 어쨋든
저런식의 사용이 안된다는겁니다.


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

운형의 이미지

do{
.
.
.
}while(0);

이런 종류의 루프가 들어가는 또다른 대표적인 예가 아무 것도 안하는 코드 일때도 있죠...

do{;}while(0);

매크로에서 ;만을 넣는 것을 허용하지 않는 컴파일러가 상당수 되는 군요.

Do you think that's the air you are breathing now?

댓글 달기

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