Media Log

내몸 아름답게 만들기 - 8점
마이클 로이젠.메멧 오즈 지음, 유태우 옮김/김영사

내몸 사용 설명서, 내몸 젊게 만들기와 같은 책을 쓴 마이클 로이젠의 최근작이다.
피부, 머릿결, 입, 손발 등 육체적으로 신체를 아름답게 만드는 방법들과 돈, 일 그리고 사랑 등의 정신적으로 행복하게 살 수 있는 방법을 다룬다. 나는 육체적인 부분에만 관심을 가지고 읽어봤다. 그 외의 부분은 별로 관심이 가지 않는데다가 다른 책 좋은 책들이 너무나도 많다.

다음은 책에서 정리한 몇가지 지침들이다.
  • 얼굴을 베개에 묻고 자지 않는다. 피부에 주름이 생기고 아침에 얼굴이 붓는다.
  • 오메가3는 만병통치약이다. 심장에 좋고 불안증과 우울증을 없애주며 여드름도 없애준다. 게다가 머릿결까지 빛나게 해준다. 어떤 음식에 오메가-3가 많이 들어있는지는 이 곳 포스트에 정리되어 있다.
  • 매주 강도가 약한 물리적 혹은 화학적 각질제거제를 사용한다.
  • 사과와 당근은 치아 미백효과가 있다. 사과는 입냄새 제거에도 도움이 된다.
  • 탈색이나 염색은 마치 음식에 인공색소를 넣는 것과 다름없다.
  • 헤어 드라이어와 고대기는 머리카락에 좋지 않다. 머리카락을 말릴 때에는 타월이 가장 좋으며 헤어드라이어를 사용하는 경우에는 낮은 열을 사용한다.
  • 동물성지방, 붉은 고기 지방 섭취는 DHT가 더 많이 생성되어 더 많은 모낭에 손상을 준다. 반면 카페인은 DHT를 낮추는 것으로 알려져왔다.
  • 혀 긁개는 입 냄새 원인의 75퍼센트를 줄여준다. 칫솔만 사용했을 경우에는 겨우 45퍼센트 줄어든다. 단지 10초만 더 투자해 혀 긁개를 혀 위에 대고 움직이기만 하면 된다.
  • 칫솔은 두 달마다 교체한다. 새로운 초음파 칫솔은 치석 제거 효과가 탁월해서 많은 치과 의사들을 놀라게 하고 있다.
  • 붉은 포도주, 커피, 차, 토마토소스, 포토와 그랜베리 주스는 확실히 치아에 얼룩을 남긴다.
초음파 칫솔은 필립스의 소닉케어 같은 제품을 말하는 것 같은데 확실하진 않다. 소닉케어는 내가 사용하고 있는 칫솔이기도 한데 상당히 만족스럽게 잘 쓰고 있다.

혀 긁개는 또 뭔가 하고 찾아봤더니 쇼핑몰들에서 혀크리너라는 이름으로 몇 천원에 팔고 있었다. 중국산 싸구려 같아서 좀 걱정되긴 하지만 그래도 한 번 사봤다.
이 책에서는 치실 또한 반드시 사용해야 한다고 권장하는데, 치실도 뭔지 몰라서 찾아봤다. 가느다란 실을 치아 사이에 끼고 실을 움직이면서 치간을 청소하는데, 저 짓을 어떻게하지. 다른 사람들은 진짜 매일 저걸 하고 사는거 맞나?
그래도 꼭 해야한다니깐 뭐 어쩔 수 없지. 치실도 사야겠다.

각질제거는 한번 해보고 싶은데 뭘 어떻게하라는건지 모르겠다. 화학 구슬(chemical beads)을 사용하는게 좋다고 말하는데 찾아봐도 잘 모르겠고 책에 좀 더 설명이 있었으면 좋았을 것 같다.



다음은 피부를 위한 음식들이다.
  • 달걀 노른자, 콩과 식물, 아보카도, 콩, 견과류
  • 연어
  • 녹차
  • 석류
  • 토마토
피해야할 화장품 원료로는
  • 요소제품
  • 라우릴황산나트륨
  • 미네랄 오일
  • 에타놀아민
  • 톨루엔
  • 디메틸아미노에타놀
들이 있다.
저작자 표시 비영리 동일 조건 변경 허락
크리에이티브 커먼즈 라이선스
Creative Commons License

http://www.benjaminlog.com/trackback/189 관련글 쓰기

  1. 내 몸 젊게 만들기 -마이클 로이젠
    // 김재호의 디지털보단 아날로그 2011/03/29 10:32 x
  1. 그나 at 2011/03/29 18:08 [edit/del]

    평소에 RSS로 받아보는 무명독자입니다. 화학적 각질제거제는 AHA나 BHA 성분이 들어있는걸 말하는것 같아요. 자그마한 구슬이 들어가는 물리적 각질제거제는 각질은 제거하지만 피부에 손상을 준다고 하더라구요. 폴라초이스 제품이 유명할꺼예요ㅎㅎ

    Reply
    • Favicon of http://www.benjaminlog.com BlogIcon 김재호 at 2011/03/30 11:26 [edit/del]

      가르쳐주셔서 감사합니다.
      폴라초이스 제품 중에 하나만 추천해주세요. 가서 살펴봤는데 뭐가 뭔지 하나도 모르겠네요.

    • 그나 at 2011/04/10 23:21 [edit/del]

      늦게 봤네요!

      건성이시면 엑스폴리언트 중에 '리지스트 데일리 스무딩 트리트먼트 with 5% AHA, 0.5% BHA' 쓰시면 될꺼예요ㅎㅎ 지성이시면 지금 BHA 제품 제대로 수입이 안되서 폴라초이스 제품 중에는 없겠네요, 딴회사는 잘 모르겠어요 :(

    • Favicon of http://www.benjaminlog.com BlogIcon 김재호 at 2011/04/11 11:15 [edit/del]

      폭풍 지성인데. 그냥 건성써도 괜찮겠죠? 안되려나.

  2. at 2011/04/05 13:19 [edit/del]

    비밀댓글입니다

    Reply
    • Favicon of http://www.benjaminlog.com BlogIcon 김재호 at 2011/04/05 13:31 [edit/del]

      에이 무슨, 인사도 못하고 와서 제가 더 미안하죠.
      전 푹 쉬면서 아주 잘 지내고 있어요.
      행복하게 지내요. 언제 또 만날꺼에요^^

  3. Oly at 2011/04/18 16:23 [edit/del]

    오랜만에 와보았습니다. ㅋㅋㅋ
    이런책을 읽고 몸매 관리 하시는군요 ㅋㅋㅋ

    Reply
  4. at 2011/04/24 22:28 [edit/del]

    비밀댓글입니다

    Reply

submit
스님의 주례사 - 8점
법륜스님 지음, 김점선 그림/휴(休)

머리가 많이 복잡해서 집근처의 공원에 바람을 쐬러 나갔다가 서점에 들러 책을 한 권 사왔다.

이 책의 부제는 행복한 결혼 생활을 위한 남녀 마음 이야기이다.
결혼을 준비하고 있는 연인들이나 결혼 후의 부부들에게 스님이 말해주는 좋은 지침들이 담겨있다.

연인과 부부 그리고 고부간의 갈등에서 생길 수 있는 화, 미움, 질투, 욕심 등의 감정을 어떻게 없앨 수 있는지 재미있게 풀어낸다.

책을 읽는 내내 어떤 사람을 생각했다.
요 며칠 동안 숨을 쉴 때마다 고통스럽고 가슴이 아팠었는데, 오늘 집에 돌아와서는 오랜만에 책상에 바른 자세로 앉아서 이 책을 읽으면서 비로소 마음이 진정되기 시작했다.

  • 문제의 본질을 파악한다.
  • 긍정적으로 생각한다.
  • 상대방을 이해한다.
  • 자신이 손해보겠다는 생각으로 산다.

이런 것들을 계속해서 수행함으로써 자기 변화를 이루게 되고 행복하게 살 수 있다고 말한다.
누구나 알고 있는 사실들이지만 이것들을 지켜 나간다는 것이 얼마나 어려운 일인가.

나는 수행이라는 단어가 참 마음에 들었다.
어디 절에 가서 아미타불 하는게 아니라, 일상 생활 속에서 꾸준히 문제점을 파악하려 노력하고 그것을 실제로 고쳐나가는 것을 연습하고 체크해보는 것이다.
내가 수행해야 할 것들을 이미 이 책에서 많이 찾았고 잊어버리게 될까봐 메모해 두었다.
이제 열심히 수행하는 일만이 남았다.
저작자 표시 비영리 동일 조건 변경 허락
크리에이티브 커먼즈 라이선스
Creative Commons License

http://www.benjaminlog.com/trackback/188 관련글 쓰기

  1. 곽재상 at 2011/03/22 17:38 [edit/del]

    이거 이거 인터넷에 떠돌아다니는 유명한 주례사.. 맞죠?
    내가 부주를 낼 건 없고 이 말로 부주를 대신한다며
    남녀 서로 이득 볼 생각하지말고 서로 베푼다고 살아라~
    하는 그 글인것 같은데 .. 한번 읽어봐야겠네요 ~

    Reply

submit

_countof 매크로

2011/03/15 06:48 | Programming
_countof 매크로는 배열의 원소 개수를 돌려주는 서비스 매크로이다. 비주얼 스튜디오 2005 부터인가 제공되었던 것 같다.
StringCchCopystrcpy_s, wcscpy_s 같은 함수들을 사용할 때 편리하게 사용할 수 있다.

_countof 매크로는 다음과 같이 생겼다.
#if !defined(_countof)
#if !defined(__cplusplus)
#define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))
#else
extern "C++"
{
template <typename T, size_t N>
char (*__countof_helper(UNALIGNED T (&_Array)[N]))[N];
#define _countof(_Array) (sizeof(*__countof_helper(_Array)) + 0)
}
#endif
#endif

C언어를 사용할 때와 C++를 사용할 때의 구현이 다르게 되어있다.
C언어에서 사용되는 방식은 대부분의 사람들이 잘 알고 있는 방식일 것이며, C++에서는 템플릿을 이용해서 배열의 개수를 구하고 있다.

여기서 궁금해해야 할 점은
  1. 템플릿을 통해 어떻게 배열의 원소의 개수를 구할 수 있는가.
  2. 도대체 왜 C와 C++을 전처리기를 사용해서까지 따로 구현했을까. 그냥 C 구현 하나만 쓰지.

1번 질문의 답은 아래 블로그에 잘 설명이 되어있다.
C++ 템플릿으로 배열의 원소 개수를 구하는 방법

2번 질문의 답은 C 구현 방식에 약간의 문제가 있기 때문이다.
배열이 아니라 포인터일 경우에 C 방식은 제대로 개수를 구해주지 못한다.
그럼 템플릿 방식은 제대로 구해주냐 하면 물론 그럴수는 없다. 그래도 컴파일 에러를 내주기 때문에 좀 더 낫다. C 방식은 컴파일이 잘 되어버리며 잘못된 결과를 돌려준다.
아래 코드를 한번 보자. 설명을 쉽게 하기 위해 매크로 이름을 바꿨다.
#define _countof_c(_Array) (sizeof(_Array) / sizeof(_Array[0]))

template <typename T, size_t N>
char (*__countof_helper(T (&_Array)[N]))[N];
#define _countof_cpp(_Array) (sizeof(*__countof_helper(_Array)) + 0)

void c_version(int* p) // int ar[] 과 같은 형식으로 넘어올 때도 마찬가지이다.
{
    printf("%d\n", _countof_c(p));
}

void cpp_version(int* p)
{
    printf("%d\n", _countof_cpp(p));
}

int _tmain(int argc, _TCHAR* argv[])
{
    int a[100];
    printf("%d\n", _countof_c(a)); // 100 올바른 결과
    printf("%d\n", _countof_cpp(a)); // 100 올바른 결과

    c_version(a); // 1 틀린 결과를 내어줘버렸다. 다행히 경고(C6384)는 발생한다.
    cpp_version(a); // cpp_version함수는 컴파일이 안된다.

    return 0;
}

여기서 배워야 할 점은,
  • C 방식 매크로를 쓸 때 언제 문제가 되는지를 알고 있어야 한다.
  • C++를 사용함에도 불구하고 해당 매크로를 C방식으로 직접 만들어서 사용하는 경우를 보았다. 그냥 _countof를 사용한다.
  • 마지막으로, 컴파일러 경고가 발생하면 무시하지 않는다.
또한, 사실 이는 _countof 의 MSDN 페이지에도 잘 나와있는 내용이다. MSDN을 읽을 때는 꼭 개요부터 See Also까지 다 읽는 습관을 들여야 한다. 특히 Remarks 섹션은 유의해야 할 사항들이나 사용자 쪽에서 궁금해 할만한 내부 구현 방식들을 다루어주므로 항상 눈을 부릅뜨고 읽어봐야한다.
저작자 표시 비영리 동일 조건 변경 허락
크리에이티브 커먼즈 라이선스
Creative Commons License

'Programming' 카테고리의 다른 글

윈도우 드라이버를 만들 때 알아야 할 기초적인 내용들  (1) 2011/05/23
Duff's Device  (0) 2011/04/07
_countof 매크로  (0) 2011/03/15
FIELD_OFFSET 매크로  (0) 2011/03/01
PAGED_CODE 매크로  (0) 2011/02/27
디렉터리의 읽기 전용 속성  (4) 2011/02/20

http://www.benjaminlog.com/trackback/187 관련글 쓰기

submit
2011년 3월 13일 날씨 맑음. 기온은 12도.
여유로운 일요일 오후이다.

정말 오랜만에 사진 폴더에 들어가 그동안 귀찮아서 미루고 있던 사진 정리를 했다. 뭔가 남아있다는 것이 얼마나 좋고 고마운 것인지 깨닫게된다.
최근에는 다시 일기를 쓰기 시작했다. 1995년부터 써왔었는데 회사에 들어갔던 해인 2006년까지 열심히 쓰다가 그 이후부터는 아주 가끔씩만 쓰게 되었다.
2006년부터 2010년까지 거의 이빨이 빠져있는 일기들을 보면서 그동안 기록해두지 않은 내 일상들이 너무 아깝다는 생각이 들었다. 마치 지난 시간들을 잃어버린 것만 같은 느낌이다.
앞으로는 아무리 바빠도 꾸준히 일기를 써야겠다.

다시 따뜻한 봄이다. 밖에 나가서 포근한 바람이나 맞고 와야겠다.


저작자 표시 비영리 동일 조건 변경 허락
크리에이티브 커먼즈 라이선스
Creative Commons License

'디지털보단 아날로그' 카테고리의 다른 글

클라우드가 더 안전하다  (8) 2011/06/13
조그만 술집, 여행  (4) 2011/04/24
디지털 기억  (2) 2011/03/13
이스트소프트의 슈퍼스타들  (2) 2011/01/05
한빛 리더스 2기 모집  (0) 2010/11/10
최고의 미드, 24시  (10) 2010/09/24

http://www.benjaminlog.com/trackback/186 관련글 쓰기

  1. at 2011/03/16 13:07 [edit/del]

    비밀댓글입니다

    Reply

submit
윤성우의 열혈 TCP/IP 소켓 프로그래밍 - 9점
윤성우 지음/오렌지미디어
이 책은 대학시절 네트워크 프로그래밍을 처음 공부하면서 봤던 책이다. 당시에도 그랬고 아직까지도 네트워크 프로그래밍 서적으로는 상당히 많이 팔린 책 중 하나인데, 작년쯤 개정판이 나왔다.
나오자마자 사놓고서는 여태껏 게으름 피우고 있다가 이제야 쭈욱 읽어봤다.

책의 표지도 그렇고 글쓴이의 문체 또한 조금 가벼운 느낌이 있어서 프로그래밍을 처음 시작하는 초보자들이나 읽어봐야할 책이라는 생각이 들수도 있다. 하지만 그렇지는 않다. 마치 어려운 내용은 다 빼고 쉬운 내용만을 설명한 것처럼 책이 술술 읽히는데, 저자가 설명을 쉽게 하는 재주가 있기 때문이지 중요한 내용들이 빠진 것은 아니다.
책장을 넘기는 내내 명불허전이라는 생각을 했다. 정말 좋은 책이다.

개정판에서는 epoll이 추가되어서 좋았다. 항상 말로만 들어보고 뭔가 너무 궁금했었다.
설명이 몇 페이지 없긴 하지만 처음부터 책을 잘 읽었으면 어렵지 않게 이해할 수 있다. IOCP를 사용해본 적이 있다면 더 쉽게 이해할 수 있을 것이다.
개인적으로 이 책의 IOCP의 설명보다는 제프리 리쳐의 Windows via C/C++의 설명이 훨씬 좋았다. 더 체계적이고 놓쳐서는 안될 세심한 부분들까지 완벽하게 다룬다. IOCP를 다루는 몇몇 책들 중에서는 제프리의 책이 가장 훌륭하다고 생각한다.

그동안 네트워크 프로그래밍을 꽤 오랫동안 안다루기는 했는가보다.
책을 읽다보니 기본적인 부분들을 포함해 많은 부분을 잊고 살고 있었는데, 이제 다시 머리 속이 채워진 느낌이다.
너무 재밌게 읽었고, 더 알고 싶은 부분도 많아서 또 다른 좋은 네트워크 책으로 보충할 생각이다.
저작자 표시 비영리 동일 조건 변경 허락
크리에이티브 커먼즈 라이선스
Creative Commons License

http://www.benjaminlog.com/trackback/185 관련글 쓰기

  1. keep at 2011/03/09 15:10 [edit/del]

    이 책 정말 명저죠

    Reply
  2. fullc0de at 2011/06/18 16:14 [edit/del]

    윤성우님도 책을 잘쓰시죠. 2003년에 이 분 책을 처음 접했는데 번역서에서 느끼지 못하는 자연스러움과 물흐르는 듯한 전개가 인상적이였죠 ㅎㅎ

    Reply
  3. BlogIcon kkkkjul at 2011/07/14 09:57 [edit/del]

    저분 대단하신듯... 출판사까지 따로 차리셧던데.
    저 대학교 1학년때 열혈강의 c,c++인기가 높아서 책이 절판된것도 아닌데 없어서 못 팔았음.

    Reply

submit
Windows 시스템 프로그래밍 - 9점
Johnson M.Hart 지음, 류광 옮김/정보문화사

오래전부터 이 책이 좋은 책이라는 이야기를 많이 들었었는데, 여태까지 못보고 있다가 이번에 4판이 번역되어 나온 김에 하나 구입해서 며칠동안 재미있게 읽었다.

저자는 이 책을 리차드 스티븐스의 유명한 고전인 APUE에 대응하는 윈도우 버전이라고 말했지만 책을 읽는 내내 자꾸 비슷한 주제를 다루는 제프리 리처의 Windows via C/C++과 비교가 되는 것은 어쩔수가 없었다.

책 중간의 동기화 오브젝트를 다루는 부분에서는 이 책이 Windows via C/C++보다 훨씬 구체적이고 많은 실례들을 들어 설명을 하고 있으며(제프리보다 재밌게 설명하는 것은 아니지만) 그 이후에 나오는 소켓과 파이프, 윈도우즈 서비스 그리고 오브젝트 보안에 대한 내용들은 Windows via C/C++에서는 다루지 않는 내용이다.
맨 마지막 챕터에서 보안 디스크립터로 ACL을 조작하는 내용은 제프리의 책뿐 아니라 다른 책들에서도 쉽게 다루지 않는 보기 힘든 내용이다. 윈도의 파일들을 리눅스 스타일의 권한(rwx--로 관리되는)처럼 관리할 수 있게 하는 재미있고 실용적인 예제와 함께해서 더 좋았다.

간간히 유닉스 시스템과 비교해서 설명해주는 저자의 코멘트들 또한 이 책의 큰 장점이다.
부록에서는 윈도 API의 유닉스와 CRT 대안 함수들을 표로서 제공해주기도 한다.

제프리리처 책의 모든 챕터를 이제는 2-3번씩 읽어서 윈도우 시스템 프로그래밍에 대해 꽤 많이 알게 되었다고 생각했는데, 이 책을 읽으면서 아직도 많은 부분을 제대로 이해 못하고 있구나 하고 느꼈다. 속상한 일이다.

책에서 옮긴 단어중 신호, 일꾼쓰레드, 스택 위넘침 등은 약간 부자연스럽긴 하지만 내용을 이해하는데는 아무런 문제가 없었다. 하지만 딱 한가지 단어가 나를 힘들게 했는데 그것은 '회부' 라는 단어였다. 가상 메모리를 커밋한다고 할 때 바로 그 커밋을 뜻하는데, 잘 매치가 되지 않아서 머리 속으로 계속 Replace를 했다.

부록에는 여러가지 I/O 방식들에 대한 성능 테스트가 나와 있다.
나는 블로그나 잡지 같은 곳에서 프로그램 성능 테스트를 해봤더니 결과가 어떻더라라고 하면 의심을 하고 잘 믿지 않는 편인데, 그것은 많은 사람들이 페이지 폴트나 캐시 등의 잡음을 고려하지 않고 테스트를 하기 때문이고, 또 그런 것들을 미리 알고 있다 하더라도 완벽히 잡음을 제거하기가 힘들기 때문이다.

책을 읽는 동안 이 책의 저자가 상당히 부지런하고 꼼꼼한 사람이라는 느낌을 받아서 벤치마크 결과에 대해 믿음도 가고 기대를 많이 하고 있었는데, 이 저자 역시 실수를 범해 누군가가 이미 벤치마크의 오류를 지적했었나보다.
아래 페이지에서 저자의 코멘트를 볼 수 있다.
http://jmhartsoftware.com/comments_updates.html
램이 1.5기가가 달린 윈도 XP가 페이지 폴트의 영향 때문에 성능이 몹시 떨어져서 나왔는데,  나중에 다시 테스트해서 올리겠다고 한다. 이런, XP하고 비스타의 I/O 성능 비교가 가장 궁금했는데.
어쨌거나 이것들을 다시 테스트 해보는 일은 엄청 귀찮을텐데 5판을 낼 때쯤에나 다시 해보지 않을까 걱정이 되기도 한다.

제프리 리처의 책이 더 이상 새 버전이 안나오는 것은 정말 아쉬운 일인데, 이 책은 5판도 6판도 계속 해서 쓰여졌으면 좋겠다.
저작자 표시 비영리 동일 조건 변경 허락
크리에이티브 커먼즈 라이선스
Creative Commons License

http://www.benjaminlog.com/trackback/183 관련글 쓰기

submit

ACE 6.0 static build

2011/03/06 17:37 | Softwares
ACE는 세상에서 가장 유명한 네트워크 프로그래밍 라이브러리이다.
여러 플랫폼에서 동작 할 수 있도록 설계/구현 되었고, 윈도우 사용자가 비주얼 스튜디오에서 쉽게 빌드할 수 있도록 솔루션 파일들까지(VC7,8,9,10) 제공해주는 서비스 정신도 갖추고 있다.

얼마전에는 ACE의 버전이 5.6에서 6.0으로 메이저 업데이트 되었다. 그런데 기존에는 static 라이브러리로 빌드하기 위한 솔루션 파일을 따로 제공해주었었는데 6.0 부터는 static 관련 sln 파일들이 없어져버렸다.

뭐지, 내가 직접 만들어 쳐넣으라는 소리인가. 서비스 정신이 사라졌나.
할 수 있는 다른 방법을 분명히 제공해주었을 것 같아서 여기저기 알아보다가 아래의 뉴스그룹 쓰레드에서 그 방법을 찾았다.
http://groups.google.com/group/comp.soft-sys.ace/browse_thread/thread/1eb2a24108d2b1c1#

자신이 원하는 솔루션 파일을 생성해주는 Perl 스크립트가 제공되는데 다음처럼 이용하면 된다.
..\ACE 6.0.1\ACE_wrapper\ace> ..\bin\mwc.pl -type vc10 -static

윈도에서 Perl을 설치하기 싫으면 근처에 접근할 수 있는 아무 리눅스로나 잠시 옮겨가서 만들어와도 되겠다.

저작자 표시 비영리 동일 조건 변경 허락
크리에이티브 커먼즈 라이선스
Creative Commons License

http://www.benjaminlog.com/trackback/184 관련글 쓰기

  1. kwon at 2011/03/21 14:41 [edit/del]

    덕분에 ace 6.0으로 쉽게 업데이트 했어요~ㅎㅎ
    타이밍이 딱 맞았네요~~ 덕분에 stack overflow에 있는 글들도 봤는데..
    도움이 되는 글들이 많이 있네요~ㅎ
    요즘 글이 많이 올라와서 좋아요~^^

    Reply

submit

FIELD_OFFSET 매크로

2011/03/01 08:00 | Programming

typedef struct tagST
{
  CHAR a;
  CHAR b;
  INT* c;
  INT64 d;
  INT cbName;
  WCHAR name[1];
} ST;
위와 같은 구조체가 있다고 하자. 네번째에 있는 멤버 d의 오프셋을 어떻게 구할지 한 번 생각해보라.

INT offset = sizeof(CHAR) + sizeof(CHAR) + sizeof(INT*);
위와 같이 코드를 작성 했다면 틀렸다. 컴파일러의 구조체 멤버 정렬값에 따라서 결과가 다르게 나올 수도 있기 때문이다.

이런 구조체의 특정 멤버에 대한 오프셋을 구해주는 서비스 매크로가 바로 FIELD_OFFSET이다.
FILED_OFFSET 매크로는 다음과 같이 생겼다.
#define FIELD_OFFSET(type, field) ((LONG)(LONG_PTR)&(((type *)0)->field))
0을 type*으로 형변환 해서 field를 참조하는 부분이 포인트인데 문법 자체에는 너무 신경쓰지 않는게 좋을 것이다.

이 매크로는 아래 처럼 사용한다.
// 첫번째 인자에 구조체 이름을 넣고 두번째 인자로 멤버 이름을 넣는다.
INT offset = FIELD_OFFSET(ST, d);
이 코드는 컴파일러의 정렬 크기나, 64비트 환경들에 상관없이 모두 제대로된 결과를 반환한다.

위 구조체를 다시 한번 보자. 마지막 멤버 name[1]이 조금 이상하게 보일 것이다.
이는 C언어에서 구조체 내에 가변길이의 데이터 멤버를 포함시킬 때 메모리를 두 덩어리로 할당하지 않고 한 덩어리로 할당하기 위해 흔히 쓰이는 기법이다. 성능상의 이점이 있기 때문에 커널 레벨 드라이버등 로우레벨로 내려갈수록 많이 쓰이지만 하이레벨 계층으로 올라오면 거의 쓰이지 않는다. 사용하기 불편하기 때문이다.
이런 구조체에는 2가지 법칙이 있는데 첫번째는 언제나 그 가변 길이 멤버가 맨 아래에 위치하고 있다는 것이며 2번째는 그 가변길이 변수의 크기를 나타내는 추가적인 변수가 꼭 존재한다는 것이다. 여기서는 cbName이다.

이제 이 name이라는 변수에 L"some string"이라는 문자열을 복사해보려고 한다. 이 구조체에 메모리를 어떻게 할당하고 값을 채워넣어야 할까.

typedef struct tagST
{
    CHAR a;
    CHAR b;
    INT* c;
    INT64 d;
    INT cbName;
    WCHAR name[1]; // 널 종료 문자열이 아니다
} ST;

int _tmain(int argc, _TCHAR* argv[])
{
    CONST WCHAR* psz = L"some string";
    INT cch = wcslen(psz);
    INT cb = cch * sizeof(WCHAR);
    
    // 첫번째 방법
    {     
        // 구조체 전체의 크기에 가변 문자열의 크기를 더해서 메모리를 할당한다.
        // 구조체에 name[1]이 이미 포함되어 있으므로 WCHAR 1개 만큼을 다시 빼주어야 한다.
        ST* p = (ST*)malloc(sizeof(ST) + cb - sizeof(WCHAR)));
        memcpy(p->name, psz, cb);
        p->cbName = cb;    
    }
    // 두번째 방법  
    {       
        // 처음부터 name의 오프셋까지만 얻어낸 뒤 cb를 더해주면 조금 더 간단하다.
        // 첫번째 방법처럼 중복된 WCHAR 만큼을 다시 빼줄 필요가 없다.
        ST* p = (ST*)malloc(FIELD_OFFSET(ST, name) + cb);
        memcpy(p->name, psz, cb);
        p->cbName = cb;
    }
    // 세번째 방법
    {
        // FIELD_OFFSET에 항상 멤버의 이름만 쓸수 있는 것은 아니다.
        // 아래처럼 배열의 인덱스에 변수를 명시하는 것도 가능하다.
        // 이 때 cb가 아니라 cch를 넣고 있는 것에 유의해야 한다.
        ST* p = (ST*)malloc(FIELD_OFFSET(ST, name[cch]));
        memcpy(p->name, psz, cb);
        p->cbName = cb;
    }

    return 0;
}

FIELD_OFFSET을 모르고 있으면 첫번째 방법처럼 조금 불편하게 코딩해야 한다는 것을 보여주기 위한 예제였다.

FIELD_OFFSET은 또한 CONTAINING_RECORD 매크로를 만들기 위해서도 쓰인다.
CONTAINING_RECORD는 재미있고 또 중요한 매크로이지만 이 곳 블로그에 이미 설명이 되어 있기 때문에 따로 쓰지 않겠다.

FIELD_OFFSET의 ANSI C 버전은 offsetof이며 stddef.h에 정의되어 있다. CONTAINING_RECORD는 container_of와 같다.
리눅스를 다루는 사람들은 offsetof 매크로를 많이 사용하는 것 같지만 나는 윈도 매크로가 더 익숙해서, 코드를 다른 플랫폼으로 이식할 필요가 없다면 offsetof 보다 FIELD_OFFSET을 사용하는 것을 더 선호한다.
양쪽의 구현은 똑같다.

저작자 표시 비영리 동일 조건 변경 허락
크리에이티브 커먼즈 라이선스
Creative Commons License

'Programming' 카테고리의 다른 글

Duff's Device  (0) 2011/04/07
_countof 매크로  (0) 2011/03/15
FIELD_OFFSET 매크로  (0) 2011/03/01
PAGED_CODE 매크로  (0) 2011/02/27
디렉터리의 읽기 전용 속성  (4) 2011/02/20
알쏭달쏭한 typedef  (7) 2011/01/04

http://www.benjaminlog.com/trackback/182 관련글 쓰기

submit