의미없는 do while 문

hwandori의 이미지

커널 코드를 보면 매크로 중에

do { } while (0)

이러한 do-while문이 있습니다. 이 의미없는 문의 뜻은 무엇인지 알고

싶습니다.

덧붙여 pgd_t나 pte_t와 같은 타입을 왜 멤버하나만 갖는 구조체로 정의

되어있는지도 알고 싶습니다. 그냥 멤버로 정의되어있는 타입으로

정의할때와 다른점은 어떤것이 있는지 알고 싶습니다.

typedef struct { unsigned long pte_low; } pte_t;
typedef struct { unsigned long pmd; } pmd_t;
typedef struct { unsigned long pgd; } pgd_t;
ohhara의 이미지

do while(0)는 여러 statement로 되어 있는 code를 macro안에 statement가 아닌 하나의 expression으로 넣고 싶을 때 사용합니다.

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

markboy의 이미지

http://www.kernelnewbies.org/faq/

위 링크 가셔서 Why do a lot of #defines in the kernel use do { ... } while(0)? 제목의 글을 찾아 보시면 좀더 자세히 설명되어 있습니다. :)

hwandori의 이미지

정말 감사합니다. 궁금증이 해소되었네요..아래 두번째 질문도 있는데..^^;

Xine의 이미지

KernelNewbies FAQ wrote:
#define FOO(x) \
        printf("arg is %s\n", x); \
        do_something_useful(x);

Now imagine using it like:

        if (blah == 2)
                FOO(blah);

This interprets to:

        if (blah == 2)
                printf("arg is %s\n", blah);
                do_something_useful(blah);;

KernelNewbies FAQ에 있는 설명의 일부 코드인데요,
지나쳤던 부분인데 깊은 뜻이 있길래 테스트를 해보았습니다.

그런데 결과는, FAQ의 내용처럼 해석되는 것이 아니라

if (blah == 2)
{
        printf("arg is %s\n", blah);
        do_something_useful(blah);;
}

와 같이 해석되는 군요. 컴파일러는 gcc 3.2.2와 MSVC 7.1에서 테스트하였습니다.

매크로의 라인마다 '\'를 붙여주었기 때문에 자동으로 처리되는 것 같은데
리눅스커널에서 do { ... } while (0) 처럼 사용하는 것은 오래된
컴파일러의 잔재일까요:roll:

--
이덕희

익명 사용자의 이미지

lachesis wrote:
KernelNewbies FAQ wrote:
#define FOO(x) \
        printf("arg is %s\n", x); \
        do_something_useful(x);

Now imagine using it like:

        if (blah == 2)
                FOO(blah);

This interprets to:

        if (blah == 2)
                printf("arg is %s\n", blah);
                do_something_useful(blah);;

KernelNewbies FAQ에 있는 설명의 일부 코드인데요,
지나쳤던 부분인데 깊은 뜻이 있길래 테스트를 해보았습니다.

그런데 결과는, FAQ의 내용처럼 해석되는 것이 아니라

if (blah == 2)
{
        printf("arg is %s\n", blah);
        do_something_useful(blah);;
}

와 같이 해석되는 군요. 컴파일러는 gcc 3.2.2와 MSVC 7.1에서 테스트하였습니다.

매크로의 라인마다 '\'를 붙여주었기 때문에 자동으로 처리되는 것 같은데
리눅스커널에서 do { ... } while (0) 처럼 사용하는 것은 오래된
컴파일러의 잔재일까요:roll:

#include <stdio.h>

#define FOO(x) \
        printf(x); \
        printf("B");

int main(int argc,char *argv[])
{
        if(argc==1) FOO("A");
}

아무 인자없이 실행하면 AB가 출력되고

인자를 주고 실행하면 B가 출력되는데요..

gcc 3.2으로 컴팔했습니다.

Xine의 이미지

무식한 실수를 저질렀네요 :oops:
성급히 테스트 하다보니 참인 조건만 가지고 테스트 해봤었네요.

MSVC 7.1에서도 혹시나 해서 테스트를 해보았으나,
역시 이와 같은 상황에서는 do { ... } while (0)문을 활용 해얄 것 같습니다.

이런 실수를 :-(

--
이덕희

powerson의 이미지

do while(0) 이코드를 보면서 왜 이렇게 했을까 많이 고민해봤지만.. 도무지 답이 안 나왔었는데.. 좋은 정보 감사드립니다. ^^

------------------------------------------------------
아직은 젊다. 모든 것을 할 수 있는 나이란 말이지.

pastime의 이미지

i386 아키텍처에서 PAE (Physical Address Extension) 을 사용하는 경우
페이지의 주소값으로 36 비트를 사용하기 때문에
하나의 long 변수로는 모든 주소값을 저장할 수 없기 때문입니다.
이러한 경우를 고려하여 코드를 유연성있게 작성한 것이라고 생각됩니다.

39 #if CONFIG_X86_PAE
40 typedef struct { unsigned long pte_low, pte_high; } pte_t;
41 typedef struct { unsigned long long pmd; } pmd_t;
42 typedef struct { unsigned long long pgd; } pgd_t;
43 #define pte_val(x)      ((x).pte_low | ((unsigned long long)(x).pte_high << 32))
44 #else
45 typedef struct { unsigned long pte_low; } pte_t;
46 typedef struct { unsigned long pmd; } pmd_t;
47 typedef struct { unsigned long pgd; } pgd_t;
48 #define pte_val(x)      ((x).pte_low)
49 #endif
jcly2의 이미지

do{..}while(0)문을 보고 왜 이렇게 쓸데없는 짓(?)을 할까 생각했던 적이 많았는데 이런 깊은 의미가 있었네요..

정보 감사합니다.

macros의 이미지

저는 아무리 읽고 또 읽어봐도 무슨 말인지 이해가 잘 가지 않습니다.
do..while문을 사용하는 이유는 여러 라인에 걸쳐 표현되는 매크로 함수를
일일히 '\' 를 주지 않고 한번에 사용한다는 말씀인가요?

초보인 저한테는 정말이지 감이 안옵니다.
죄송하지만 좀더 쉽게 설명해주셨으면.... :oops:

익명 사용자의 이미지

#define MACRO(x) aaa(x);\
                             bbb(x);

int main()
{
       if(....) MACRO(0);
}

위 코드는 preprocessing을 거치면

int main()
{
       if(....) aaa(0);
       bbb(0);
}

이 되서 aaa(x)부분만 if에 걸리게 됩니다.

하지만 do while로 묶어주면 그렇지 않죠.

ftty의 이미지

#include <stdio.h>

#define FOO(x) \
        printf(x); \
        printf("B");

int main(int argc,char *argv[])
{
        if(argc==1) FOO("A");
}

여기서 FOO(x)뒤에 ;을 붙여보았더니

#include <stdio.h>

#define FOO(x); \
        printf(x); \
        printf("B");

int main(int argc,char *argv[])
{
        if(argc==1) FOO("A");
}

AB가 인자에 상관없이 무조건 출력되더라구여....
;이 두개이기때문에 에러나야 하지 않나여???

우리 모두 리얼리스트가 되자. 그러나 가슴에는 불가능한 꿈을 갖자!!!

morris의 이미지

int main(int argc,char *argv[])
{
        if(argc==1) ; printf("A"); printf("B");;
}

gcc에서는 이렇게 변환되는군요

gcc -C -E로 하신후에 처리되는거 보시면 아실겁니다.

ftty의 이미지

그러네요....
궁금증이 풀렸습니다.

감사^^

우리 모두 리얼리스트가 되자. 그러나 가슴에는 불가능한 꿈을 갖자!!!

tinywolf의 이미지

으음...
저도 예전에 저런 매크로에 관한 문제를 해결했었는데..
어떻게 했는지 다시 뒤져 보니 이렇게 썼더군요.. ㅎㅎ

Quote:
{ ... } 무의미한변수

#if defined(_DEBUG) || defined(TRACE_DEBUG)

#include <windows.h>
#include <tchar.h>

#ifndef TRACELOG_FILENAME
#	define TRACELOG_FILENAME "trace.log"
#endif

class CTracer
{
public:
	static CTracer* s_pcTrace;
	CRITICAL_SECTION m_crit;
	TCHAR* m_szFileName;
	TCHAR m_szBuffer[512];

	static void GrobalInitial(void);

	CTracer(const TCHAR* szLogFile);
	virtual ~CTracer();

	void Lock(void);
	void printf(const TCHAR* szFormat, ...);
	void Unlock(void);
};

#define TRACER CTracer::s_pcTrace

#define TRACE_INIT CTracer::GrobalInitial();

#define TRACE_PRINTF CTracer::s_pcTrace->printf

#define FUNC_OPEN(x); \
	TRACER->Lock(); \
	unsigned long __trace_time = GetTickCount(); \
	TCHAR* __trace_func = _T(x); \
	TRACER->printf(_T("%s | %s(%4d) | '%s' ┰ \n"), _T(__TIME__), strrchr(_T(__FILE__), _T('\\'))+1, _T(__LINE__), __trace_func); \
	TRACER->Unlock();

#define FUNC_RETURN_VOID \
	{ \
		TRACER->Lock(); \
		TRACER->printf(_T("%s | %s(%4d) | '%s' ┸ | time %dms\n"), _T(__TIME__), _tcsrchr(_T(__FILE__), _T('\\'))+1, _T(__LINE__), __trace_func, GetTickCount() - __trace_time); \
		TRACER->Unlock(); \
		return; \
	} __trace_time
#define FUNC_RETURN(x) \
	{ \
		TRACER->Lock(); \
		TRACER->printf(_T("%s | %s(%4d) | '%s' ┸ | time %dms | return-val 0x%08X(%d)\n"), _T(__TIME__), _tcsrchr(_T(__FILE__), _T('\\'))+1, _T(__LINE__), __trace_func, GetTickCount() - __trace_time, (unsigned long)x, (unsigned long)x); \
		TRACER->Unlock(); \
		return(x); \
	} __trace_time
#define FUNC_TRACE(x) \
	{ \
		TRACER->Lock(); \
		TRACER->printf(_T("%s | %s(%4d) | '%s' ┃ | time %dms | "), _T(__TIME__), _tcsrchr(_T(__FILE__), _T('\\'))+1, _T(__LINE__), __trace_func, GetTickCount() - __trace_time); \
		TRACER->printf(x); \
		TRACER->printf(_T("\n")); \
		TRACER->Unlock(); \
	} __trace_time
#define FUNC_PRINTF \
	{ \
		TRACER->Lock(); \
		TRACER->printf(_T("%s | %s(%4d) | '%s' ┃ | time %dms | "), _T(__TIME__), _tcsrchr(_T(__FILE__), _T('\\'))+1, _T(__LINE__), __trace_func, GetTickCount() - __trace_time); \
		TRACER->printf
#define PRINTF_END \
		; \
		TRACER->printf(_T("\n")); \
		TRACER->Unlock(); \
	} __trace_time

#else

inline void __trace_voidf(const char* szFormat, ...)
{ }

#define TRACE_INIT
#define TRACE_PRINTF __trace_voidf
#define FUNC_OPEN(x);
#define FUNC_RETURN_VOID return
#define FUNC_RETURN(x) return(x)
#define FUNC_TRACE(x);
#define FUNC_PRINTF __trace_voidf
#define PRINTF_END

#endif

#define _TI TRACE_INIT
#define _TP TRACE_PRINTF
#define _FO	 FUNC_OPEN
#define _FRV FUNC_RETURN_VOID
#define _FR  FUNC_RETURN
#define _FT  FUNC_TRACE
#define _FP  FUNC_PRINTF
#define PF_  PRINTF_END

ㅡ_ㅡ;

익명 사용자의 이미지

ncubic

익명 사용자의 이미지

중복이 되는 주제입니다...
검색키워드를 무엇을 해야 찾을 수 있는지... --;
링크 걸려고 했는데...잘 안되네요...

댓글 달기

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