Media Log

[Programming]에 해당되는 글 57

  1. h 어썸블로그, 개발자를 위한 블로그 뉴스 앱 5 2017.02.21
  2. h TypeScript, 타입에 대한 고찰 2015.05.05
  3. h 시니어 프로그래머 2 2015.02.03
  4. h Windows Runtime 이야기 1 2014.12.05
  5. h 눈물나는 그래프 2 2014.08.25
  6. h 방준영의 블로그 2014.06.06
  7. h 프로그래머의 5가지 성향 2014.03.15
  8. h 프로그래밍의 첫 번째 규칙: It's Always Your Fault. 1 2014.03.06
  9. h 윈도우즈 PE 파일의 구조 2013.03.24
  10. h 윈도8에서의 UAC 관련 중요한 변화 2012.05.28
  11. h 매크로의 가변인자를 또 다른 매크로로 넘기기 2012.04.16
  12. h 내가 좋아하는 국내 프로그래밍 블로그들 11 2012.04.12
  13. h CString 의 비밀 6 2012.04.12
  14. h 쉘의 파일 오퍼레이션을 잡아챌 수 있는 ICopyHook 인터페이스 2012.04.06
  15. h 메인 쓰레드가 종료되면 프로세스도 종료되는 것 아닌가요? 2012.03.26
  16. h 어떻게 함수의 undecorated name을 추측 할 수 있을까? 3 2012.02.12
  17. h 왜 static 멤버 함수에는 const를 붙일 수 없을까? 2012.02.06
  18. h SetFilePointer 보다는 SetFilePointerEx를 사용해야 한다 2 2012.01.16
  19. h GetLastError 함수 사용의 흔한 실수 2012.01.13
  20. h NTFS에서 Sparse 파일을 만들기 3 2012.01.03
  21. h 16TB 크기의 파일을 만들어내려면 얼마나 오래 걸릴까? 2012.01.01
  22. h 구조체의 패킹에 대한 이야기 4 2011.12.19
  23. h 프로그래머에게 가장 굴욕적인 순간은? 2011.12.19
  24. h C/C++ 코딩 스타일 이야기 8 2011.10.24
  25. h 레지스트리의 volatile 옵션 2011.09.27
  26. h 알아두면 유용한 MoveFileEx 함수의 펜딩 옵션 2011.07.17
  27. h 메모리를 해제하기 전에 왜 널 체크를 하는걸까? 6 2011.05.29
  28. h 윈도우 드라이버를 만들 때 알아야 할 기초적인 내용들 2 2011.05.23
  29. h Duff's Device 2011.04.07
  30. h _countof 매크로 2011.03.15

블로그 이전했습니다.

https://jeho.page/programming/2017/02/21/%EC%96%B4%EC%8D%B8%EB%B8%94%EB%A1%9C%EA%B7%B8-%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EB%89%B4%EC%8A%A4-%EC%96%B4%ED%94%8C.html

 

어썸블로그, 개발자를 위한 뉴스 어플

요즘엔 사람들이 페이스북같은 SNS 에서 정보를 많이 얻어가는 것 같지만, 여전히 블로그는 좋은 정보의 원천지이다. 개발자와 IT 서비스를 하는 사람들을 위해 좋은 글들이 올라오는 블로그들을

jeho.page

 

'Programming' 카테고리의 다른 글

TypeScript, 타입에 대한 고찰  (0) 2015.05.05
시니어 프로그래머  (2) 2015.02.03
Windows Runtime 이야기  (1) 2014.12.05
눈물나는 그래프  (2) 2014.08.25
방준영의 블로그  (0) 2014.06.06

쉬는 날을 틈타 Build 2015 동영상을 다운 받아서 하나씩 보는 중이다. Async/Await 이라는 부제에 끌려서 들어갔는데, 이 제목은 낚시였고 TypeScript 에 대한 설명이 주를 이룬다.

TypeScript 자체에는 큰 관심이 없지만, 앤더스 헤일스벅이 타입이라는 것에 대해 그동안 고민해온 고찰을 들어볼 수 있었고 또 전설의 레전드가 직접 코딩하는 것을 구경하는 것만으로도 무척 즐겁게 봤다.


동영상은 아래 링크에서 볼 수 있다.

https://channel9.msdn.com/Events/Build/2015/3-644



'Programming' 카테고리의 다른 글

어썸블로그, 개발자를 위한 블로그 뉴스 앱  (5) 2017.02.21
시니어 프로그래머  (2) 2015.02.03
Windows Runtime 이야기  (1) 2014.12.05
눈물나는 그래프  (2) 2014.08.25
방준영의 블로그  (0) 2014.06.06

블로그 이사했습니다.

https://jeho.page/essay/2015/02/03/%EC%8B%9C%EB%8B%88%EC%96%B4-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8.html

 

시니어 프로그래머

보통 우리 나라 IT회사들의 평균 나이는 31-33세 인데 내 나이가 이제 우리 나이로 35살이니 평균 보다 조금 늙은(?) 나이인 것 같다.

jeho.page

 

'Programming' 카테고리의 다른 글

어썸블로그, 개발자를 위한 블로그 뉴스 앱  (5) 2017.02.21
TypeScript, 타입에 대한 고찰  (0) 2015.05.05
Windows Runtime 이야기  (1) 2014.12.05
눈물나는 그래프  (2) 2014.08.25
방준영의 블로그  (0) 2014.06.06

Windows Runtime 이야기

2014. 12. 5. 02:40 | Programming

아래 페이지로 포스팅 이전했습니다.

https://jeho.page/essay/2014/12/05/windows-runtime.html

 

Windows 유니버셜 앱 개발 경험담

꽤 오랫동안 윈도 프로그래밍에서 떨어져 살다가 윈도폰은 어떨지 궁금해서 문득 윈도폰 하나를 중고로 구입해본 적이 있었다. 그게 NT 커널이 올라가있는 윈도폰 8.0 이었다. 세컨드 폰으로 장

jeho.page

 

'Programming' 카테고리의 다른 글

TypeScript, 타입에 대한 고찰  (0) 2015.05.05
시니어 프로그래머  (2) 2015.02.03
눈물나는 그래프  (2) 2014.08.25
방준영의 블로그  (0) 2014.06.06
프로그래머의 5가지 성향  (0) 2014.03.15

눈물나는 그래프

2014. 8. 25. 22:24 | Programming


예전에 존 레식의 매일 매일 코딩하기라는 글을 본 기억이 문득 떠올라서 나도 내 Github 그래프를 한번 열어봤다.

8년이 되는 경력 동안 꾸준히 저 정도 그래프를 그린 것 같은데 기대만큼 실력은 늘지 않는 것 같다.

존 레식 같은 해커가 되려면 몇 년이나 이렇게 살아야 하는 걸까. 그래서 눈물나는 그래프.


'Programming' 카테고리의 다른 글

시니어 프로그래머  (2) 2015.02.03
Windows Runtime 이야기  (1) 2014.12.05
방준영의 블로그  (0) 2014.06.06
프로그래머의 5가지 성향  (0) 2014.03.15
프로그래밍의 첫 번째 규칙: It's Always Your Fault.  (1) 2014.03.06

방준영의 블로그

2014. 6. 6. 14:09 | Programming

내가 좋아하는 국내 프로그래밍 블로그들에서 살짝 언급했던 방준영의 블로그가 다시 돌아왔다.

최근에는 국내 프로그래밍 블로그들이 거의 전멸 하다시피 해서 해커뉴스만 울며 겨자먹기로 보면서(왜냐면 영어를 잘 못하기 때문에) 삶을 살아가고 있었는데, 이런 좋은 블로그가 돌아와줘서 정말 기쁘다.

이번에는 중간에 잠적(?)하지 않고 꾸준히 좋은 글들을 많이 써줘서 더 많은 사람들이 그의 블로그를 찾고, 나처럼 즐거움을 느꼈으면 좋겠다.

'Programming' 카테고리의 다른 글

Windows Runtime 이야기  (1) 2014.12.05
눈물나는 그래프  (2) 2014.08.25
프로그래머의 5가지 성향  (0) 2014.03.15
프로그래밍의 첫 번째 규칙: It's Always Your Fault.  (1) 2014.03.06
윈도우즈 PE 파일의 구조  (0) 2013.03.24


1. 쉬운 문제를 어렵다고 말하며 매번 포기하는 사람.
2. 어려운 문제를 쉽다고 말하며 틀린 답을 내는 사람.
3. 어려운 문제를 쉽다고 말하며 쉬운 솔루션으로 그저 그런 답을 내는 사람.
4. 어려운 문제를 어렵다고 말하며 제대로 된 솔루션을 만들어내는 사람.
5. 어려운 문제를 쉽다고 말하며 제대로 된 솔루션을 만들어내는 사람.

1,2,3 번은 많이 봤는데 4번은 몇 명 만나보지 못한 것 같다. 5번은 아직까진 한 명도 보지 못했다.


블로그 포스팅 이전

https://jeho.page/programming/2014/03/06/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%98-%EC%B2%AB-%EB%B2%88%EC%A7%B8-%EA%B7%9C%EC%B9%99.html

 

프로그래밍의 첫 번째 규칙: It’s Always Your Fault.

아마 이게 어떤 느낌인지 알 겁니다. 우리 모두가 한 번쯤 겪었던 일입니다. 코드를 수십 번 읽어 보았으나 어디가 문제인지 발견하지 못하고 있습니다. 그 코드에는 여러분이 도저히 처리할 수

jeho.page

 


Portable Executable Structure이미지 출처 https://code.google.com/p/corkami/wiki/PE101

엄청나게 잘 정리된 그림을 발견했다. 아름답지 아니한가.

http://www.brianbondy.com/blog/id/140/

위 포스트를 읽고서 윈도8에 꽤 큰 변화가 생겼다는 것을 알았다.

지금까지는 UAC를 꺼둔다면 XP와 같은 환경이라고 생각해도 별 문제가 없었지만, 이제는 더 이상 아니라는 뜻.


If (IsUacDisabled())

{

}


만일 이런 이상한 얍삽이 코드를 즐겨 사용했다면, 이제 그 결정에 대해서 벌을 받을 시간이다.

살다보면(?) 매크로에서 받는 가변 인자를 또 다른 매크로로 쑤셔넣고 싶은 경우가 있다.

#define MACRO_1(abcfn(a, b, c) #define MACRO(...) MACRO_1(__VA_ARGS__)

짠, 이렇게 하면 된다.

그렇다. 아무 테크닉이 필요없이 그냥 쑤셔넣으면 된다.

그런데 위 코드는 GCC에서는 잘 동작하지만 VC에서는 동작하지 않는다. 그렇다고 해서 가변인자는 다른 매크로로 건넬 수가 없구나 하고 오해하면 안된다. 이것은 그냥 비주얼 스튜디오의 버그일 뿐이다.

#define MACRO_1(abcfn(abc)
#define MACRO_1_(args_listMACRO_1 args_list
#define MACRO(...) MACRO_1_((__VA_ARGS__))

비주얼 스튜디오에서는 위와 같은 얍삽이를 통해서 이를 회피할 수 있다. __VA_ARGS__ 주위를 한 겹 더 괄호로 둘러싸서 또 다른 매크로로 넘기는 것을 주의해서 봐야한다.


그래서 내가 하고 싶은 말은,


이 버그가 정말 거지 같다고 생각된다면

http://connect.microsoft.com/VisualStudio/feedback/details/380090/variadic-macro-replacement

여기 가서 upvote를 해주세요.

내 피드리더에는 등록되어있는 블로그가 700여개 쯤 있다.

그 중에는 새로운 글이 올라올 때마다 가슴이 설레는 몇몇 블로그들이 있다. 그 중 우리나라 저자가 운영하는 3개의 블로그를 소개하려고 한다.


1. 메아리 저널

정말 엄청난 실력을 가진 해커이다. 특정 플랫폼이나 언어에 상관없이 여러 주제로 재밌는 글을 쓴다. 가끔 기괴한 코드 골프 내용이 올라오기도 하는데 그런걸 쳐다보고 있다 보면 자괴감에 빠지기도 한다.

어쨌거나 나는 그의 글이 너무나도 좋아서 언젠가는 주말 이틀 동안 내내 방구석에 누워서 2004년부터인가 썼던 모든 글을 다 읽어본 적도 있었다. 가끔씩 이상한 오락실 얘기도 쓰고는 하는데 그런 글조차 재밌다. 블로그에 댓글로 피드백을 할 수가 없어서 애독자로서 좀 아쉽긴 하지만 본인이 그에 대해 많이 고민해 본 듯하니 어쩔 수 없는 일이다.


2. art.oriented

프로그래머가 몰랐던 멀티코어 CPU 이야기를 쓴 저자이다. 주로 윈도 프로그래밍이나 시스템 프로그래밍 이야기를 다루는데 글들이 재밌을 뿐더러 배울 점도 많다. 이 블로그 역시 거의 모든 글을 다 읽었다. 아마 프로그래밍 기술을 다루는 우리나라 블로그들 중 가장 피드백이 많이 왔다갔다 하고 방문자 수도 많은 블로그가 아닐까 싶다.


3. 김용묵의 절대 공간

이 블로그는 비교적 최근에 알게되었다. 글들은 아주 오래전부터 꾸준히 작성되어 왔는데 써있는 글의 질과 양에 비해 일방문자수는 상당히 적다. 윈도 프로그래밍에 대해서만 다룬다. 윈도 역사에 대해서 글을 쓸 때는 레이몬드 첸을 보는 느낌이 들기도 한다. 철도와 종교 이야기도 종종 꺼내는데 나는 그런 주제는 관심이 없어서 건너 뛰고 읽는다.


그러고보니 이 블로그들 이상으로 예전에 정말 좋아했던 블로그가 있었다. 바로 방준영의 블로그. 2009년도 즈음이었던가? 어느 날 아침에 그의 블로그를 발견하고는 오아시스라도 발견한 것 처럼 기뻤던 날이 있었다. 거의 매일 같이 좋은 글들이 올라와서 정말 행복하게 읽어가고 있었는데 언제부터인가 새 글이 더 이상 올라오지 않았고 심지어는 기존에 썼던 글마저 사라져 버렸다. 안타까운 일이다. 준영님. 혹시라도 이 글을 보신다면 돌아와주세요. 엉엉.


나는 미투데이나 트위터가 싫다. 페이스북도 싫다. 이 잡 것들이 나오고 나서 사람들은 블로그에 글을 잘 쓰지 않는다.

돌아오라 블로거들이여. 맛집 블로거 말고 프로그래머들 말이여.

그럼에도 불구하고 영어 블로그는 여전히 좋은 블로그들이 엄청나게 많다. 하지만 영어 블로그를 읽는 것은 정말 고통스러운 일이다. 내 피드 리더에는 나중에 읽으려고 마킹해둔 글들이 잔뜩 쌓여있는데 그것들 대부분은 영어 포스트이다. 한 번 읽으려면 크게 심호흡부터 하며 각오를 단단히 하고는 한다. 그리고 나는 그렇게 심호흡을 자주 하지 않기 때문에 오늘도 마킹만 해두는 글들이 계속 늘어간다.

그러니 이렇게 우리말로 좋은 글을 써주는 사람들이 어찌 고맙지 않겠는가. 좋은 국내 블로그들이 더 많이 생겼으면 좋겠다.

CString 의 비밀

2012. 4. 12. 11:55 | Programming

블로그 이전했습니다.

 

이전한 포스팅 주소

 

https://jeho.page/programming/2012/04/12/CString%EC%9D%98-%EB%B9%84%EB%B0%80.html

 

CString의 비밀

다음 코드를 실행시켜보면 "abc"가 잘 출력이 될까?

jeho.page

 

C++에서 함수 이름이 맹글링 되는 것은 다들 알고 있는 사실일 것이다.
링커 오류를 만나게 되면 원인을 분석하기 위해 때때로 함수의 오리지날 이름이 알고 싶을 때가 있다. 마이크로소프트의 도구로 만들어진 함수들에 대해서는 undname 이라는 프로그램이 바로 그런 일을 해준다.

레이몬드 첸의 한 포스트를 읽다가 그는 단순한 함수들에 대해서는 undname을 사용하지 않고도 한눈에 척 알아볼 수 있는 것 같다는 느낌을 받았다.
어떻게 그런 일을 할 수 있는지 알아보다가 강성훈씨가 쓴 이 포스트를 보게 되었다. 그가 말하는 것처럼 아마 현재까지 가장 잘 정리된 자료라는데 동의한다. 어린 나이에 정말 대-_-단 하다고 밖에는 말할 수 없다.

...하지만 나는 한참 살펴보다가 결심했다.
'빌어먹을. 나는 그냥 undname이나 써야겠다.'

흐아, 생각처럼 간단한 일이 아니었다.
그런데 레이몬드 첸은 정말 간단한 함수 정도는 추측할 수 있는 것일까? 아직도 잘 모르겠다.
NTFS에서 만들 수 있는 단일 파일의 가장 큰 크기는? 16테라. 빙고.
그럼 NTFS 상에서 16 테라 바이트의 파일을 만들기 위해서는 얼마나 시간이 걸릴까?

답은 여기에 있다.

16TB 라는 숫자의 이미지가 머리 속에 잘 안그려져서 내 추정보다 훨씬 큰 기간이 나와버렸는데, 가만히 계산해보니 그렇게 놀라운 숫자도 아니다. 16TB라는 숫자를 너무 얕봤나보다.
프로 당구 선수에게 가장 굴욕적이고 부끄러운 순간이 있다면 바로 키스를 내는 일일 것이다. -아마추어 세계에서는 삑사리를 내는 것일지도 모르지만. 축구 선수에게는 알까기를 당하는 것, 농구에서는 블록킹을 당하는 순간일지도 모르겠다.

만일 프로그래머에도 이런 순간을 하나 꼽으라면 나는 버그 관리 시스템에서 이슈를 해결 처리 했는데 재등록이 되거나 그로인해 다른 버그를 유발하는 것이라 생각한다. 버그가 재등록된다는 것은 제대로 테스트 해보지 않았다는 것이고 다른 버그를 유발 시켰다면, 앞뒤 로직을 충분히 검토하지 않고 버그가 발생한 바로 그 곳만 바라보고 버그를 수정했다는 뜻이다. 부끄러워하고 반성해야 한다.
뒤돌려치기(우라마시)를 치는데 그냥 운에 맡기고 친 후 쫑이 날 수도 있는게 당연하다고 생각한다면 절대 당구 실력이 늘지 않는다. 프로그래머에게도 마찬가지라고 생각한다.

갑자기 이런 이야기가 생각이 난 것은 레이몬드 첸의 한 포스트를 읽고 나서였는데, 옛날 처음에 회사에 들어갔을 때의 내 모습이 떠올랐기 때문이다. (그냥 글을 읽는 중에 그런 일들이 떠올랐던 것 뿐, 지금 말하는 이야기가 레이몬드 첸이 말한 요지과 관련이 있는 것은 아니다.)

나는 프로그램을 디버그 하다가 널 포인터 접근 등의 예외로 프로그램이 크래시 된 것을 확인하였으면 해당 부분을

if (ptr)
{
 // *ptr을 사용
}

등으로 널 포인터 체크를 추가하여 수정하고는 이슈를 완료시키곤 했다. 하루에 버그를 10개 넘게 고친 날도 많았다.

꼭 널 포인터만의 이야기를 하는 것은 아니다. 버그가 발생한 앞뒤 로직을 충분히 점검하지 않고, 그 곳만 쳐다본채 코드를 수정하는 것에 대한 문제점을 이야기 하고 있는 것이다. 그 때 그 버그들이 정말 고쳐진 건지 아직도 모르겠다.
부작용도 많았지만, 또 어떻게 어떻게 메꾸어 내었고, 이슈 해결량이 많았기 때문에 나는 생산성이 좋다는 평가를 받았다. 지금 생각하면 부끄러운 일이다. 나는 그냥 버그를 숨겼을 뿐이다. 

언제부턴가 그런 것이 잘못된 것이라는 것을 깨닫게 되었다. 아마도 나의 스승(?)이 일을 처리하던 모습을 유심히 관찰하면서였던 것 같다.
그 이후로는 버그가 발생했을 때 항상 전후 함수들을 모두 따라가보면서 로직들을 점검하고 어디가 문제인지, 널 포인터 체크를 추가해서 버그를 해결해도 되는건지, 또는 널 포인터가 들어오게 하는 것이 잘못인지 등을 꼼꼼히 따져보고 코드를 작성하는 습관을 들이게 되었다.

이런 습관을 들인 후에는 버그가 재등록이 되거나 다른 버그를 유발하는 일이 점점 줄어갔다. 예전처럼 하루에 버그를 10개 넘게 고치지는 못하지만 지금도 여전히 생산성이 좋다는 평가를 받는다. 다시 재등록 되는 버그에 대한 작업을 할 필요가 없기 때문이다. 코드를 추가할 때마다 다른 버그가 발생해서 고치고 또 고치고 하면서 시간을 보내는 경우를 본 적이 있는가? 주위를 유심히 잘 살펴본다면, 얼마나 그런 경우가 많은지에 대해서 놀라게 될 것이다. 어쩌면 여러분 자신일지도 모른다.
하루에 버그를 1개를 고치더라도, 코드를 10줄을 작성하고 퇴근하더라도 제대로 하는 것이 더 프로젝트를 빠르게 진행하는 길이라는 것을 이제는 확실히 알고 있다.

만일 여러분이 팀장이나 프로젝트 관리자라면, 10분만에 버그를 고치는 사람에게는 칭찬을 해줄 것이 아니라, 혹시 저런 문제가 있는 것은 아닌지 잘 관찰해봐야한다. 그리고 만일 어떤식으로든 가르침을 주어 변화시킬 수 있다면 여러분 또한 멋진 스승이고 멘토이다.
프로그램을 처음 배울 때는 거의 정신병자 수준으로 코딩 스타일에 집착했었는데 나이가 들어가면서 코딩 스타일에 조금씩 둔감해져가고 있다.
대학 때는 들여쓰기를 tab으로 했었는데 첫번째 회사에서 space가 규칙이라고 꼭 그렇게 쓰라고 강제했다. 나는 tab을 버리기 싫었지만 규칙을 어기지 않기위해 그렇게 쓰다보니 space가 너무 좋아져버렸다. 2번째 회사에서는 다시 tab을 사용하라고 한다. 좀 촌스럽네? 아직도 tab을 쓰는데가 있었나 정도의 생각은 들지만 거부감 없이 받아들일 수 있었다. 그 외의 다른 스타일들도 비슷하다.

그래도 여전히 눈에 거슬리고 바꿔버리고 싶은 욕구가 드는 C/C++ 코딩 스타일이 2가지가 있는데 그 중 하나는
if (0 == str.Length())
{
}
위처럼 상수를 좌측에 쓰는 코드이다.
프로그램을 읽기에도 불편하고 쓸 때 또한 불편한데 도대체 왜 상수를 왼쪽에 쓰는가.

아마 어떤 사람들은 그렇게 써야 == 연산자 대신 = 를 사용해버리는 실수를 방지할 수 있어요, 라고 대답할지도 모른다. 하지만 요즘 컴파일러는 이런 실수를 경고로 가르쳐주는 기능을 다 가지고 있는데 굳이 저렇게 쓸 필요가 있는가? 컴파일러나 정적분석툴의 도움를 받을 수 없는 상황에서나 어쩔수 없이 사용하던 구식 방법인데 이를 무작정 따라하는 사람들이 많다. 다음 코드는 조금 더 보기에 안좋다.
if (MAX_PATH <= str.Length())
{
}
'상수를 왼쪽에 써야 실수를 줄일수 있다고 했지'. 라고 생각없이 이 말을 받아들인 사람들은 == 이 아니라 비교연산자를 사용할 때에도 모든 상수는 죄다 왼쪽에 써버린다. 위 코드를 읽을 때 머리가 2번씩 돌아가는 것 같지 않은가?

또 한가지 싫어하는 C/C++ 스타일은
bool xxx = fOk;
if (xxx == true)
{
}
이렇게 불린 테스트를 true나 false와 명시적으로 비교하는 것이다.

아래 strcmp 함수의 경우 처럼 표현식의 결과가 불린 값이 아닌 경우에는(strcmp의 리턴값은 정수이다) 같은 타입으로 명시적으로 비교를 해서 표현식을 참 혹은 거짓으로 맞추어 주는 것이 의미가 있다.
if (!strcmp(xxx, yyy)) // 이보다는
if (strcmp(xxx, yyy) == 0) // 이게 더 낫다고 생각한다.
하지만 이미 어떤 변수나 식이 이미 참과 거짓을 나타내고 있다면 또 다시 그것을 true나 false와 비교하는 것은 명백한 중복이다. 나는 그런 경우는 그냥
if (xxx)
{
}

또는
if (!xxx)
{
}
이렇게 쓰는 것을 선호한다.

위에서 처럼 true와 비교하는 것보다 1로 정의된 대문자 TRUE를 비교하는 것은 훨씬 나쁘다.
if (xxx == TRUE)
{
}
xxx 값이 0도 아니고 1도 아닌 값(하지만 참인)을 가진 경우에는 골탕을 먹게 되기 때문이다.

오늘 stackoverflow를 구경하다가 재밌는 사실 하나를 알게되었다.
많은 사람들이 나만큼이나 위 두가지 스타일을 싫어한다는 것이다.
어떤 코딩 스타일이 가장 거지같다고 생각하나요?

내가 위에서 말한 2가지 스타일이 1등과 3등을 차지 했다니 아마 저런 스타일을 사용하는 사람들은 잘 믿기지 않을 것이다.
재밌는 답변과 댓글들이 많으니 관심있는 사람들은 위 포스트를 한번 읽어보기 바란다.
나는 아래 댓글이 가장 재밌고 인상적이었다.
Damn. We say "if it's raining, open your umbrella" and NEVER "if it's true that it's raining, take your umbrella"... Testing explicitely against boolean is as verbose and as un-natural as the second example

'Programming' 카테고리의 다른 글

알아두면 유용한 MoveFileEx 함수의 펜딩 옵션  (0) 2011.07.17
메모리를 해제하기 전에 왜 널 체크를 하는걸까?  (6) 2011.05.29
Duff's Device  (0) 2011.04.07
_countof 매크로  (0) 2011.03.15
FIELD_OFFSET 매크로  (1) 2011.03.01

Duff's Device

2011. 4. 7. 07:47 | Programming
Duff's Device는 Tom Duff라는 사람이 1983년도에 생각해낸 switch 문장을 사용한 loop unwinding 얍삽이이다.
위키피디아에는 다음 코드가 인용되어져 있다.
send(to, from, count)
register short *to, *from;
register count;
{
    register n = (count + 7) / 8;
    switch(count % 8) {
    case 0: do{ *to = *from++;
    case 7:     *to = *from++;
    case 6:     *to = *from++;
    case 5:     *to = *from++;
    case 4:     *to = *from++;
    case 3:     *to = *from++;
    case 2:     *to = *from++;
    case 1:     *to = *from++;
            } while(--n > 0);
    }
}
얼핏보면 switch 문장안에 do while 루프가 들어있는 것이 컴파일도 되지 않을 것처럼 보이지만 신기하게도 어느 컴파일러에서나 잘 컴파일된다.

이 코드가 컴파일 가능한 이유는 C언어의 switch 문법이
switch ( expression )
{
case constant-expression :
    statement-list
    break ;

case constant-expression :
    statement-list
    break ;

...

default :
    statement-list
    break ;
}
이 아니라 단지

switch ( expression )
    statement
이기 때문이다.

switch는 if문이나 for문 처럼 바로 뒤에 단일 문장이 올 수도 있고 블록으로된 문장들이 오는 것이 가능하다. 꼭 case 레이블이 바로 뒤따르지 않아도 된다는 뜻이다.
즉, 아래와 같은 코드도 적법하다.
switch(nn % 4)
{
for(; nn > 0; nn -= 4)
    {
case 0:    *destp++ = *srcp++;
case 3:    *destp++ = *srcp++;
case 2:    *destp++ = *srcp++;
case 1:    *destp++ = *srcp++;
    }
}

다시 처음에 나왔던 Duff's Device의 switch문을 보면, 그 코드는 마치 아래와 같이 동작할 것이다. 루프의 중간부분 부터 끼어들어갈 수 있다는 것이 중요하다.
switch(count & 7)
{
case 0 : goto lbl0;
case 1 : goto lbl1;
case 2 : goto lbl2;
case 3 : goto lbl3;
case 4 : goto lbl4;
case 5 : goto lbl5;
case 6 : goto lbl6;
case 7 : goto lbl7;
}

lbl0:
    while(count > 0)
    {
        handle_one();
        count--;
lbl1:
        handle_one();
        count--;
lbl2:
        handle_one();
        count--;
lbl3:
        handle_one();
        count--;
lbl4:
        handle_one();
        count--;
lbl5:
        handle_one();
        count--;
lbl6:
        handle_one();
        count--;
lbl7:
        handle_one();
        count--;
    }

이런 코드가 보통의 루프보다 빠른 이유는 불필요한 비교문을 줄여주기 때문이다.
do {                
    *a = *b++;
} while (--count > 0);
위 코드에서 몇번이나 count가 0과 비교 되겠는가. b의 포인터 증가 연산은 몇번 일어나겠는가. 쉽다. count 번이다.
Duff's device에서는 루프를 손으로 풀어서 씀으로써 count / 8 만큼으로 테스트 횟수를 줄일 수 있게 된다. (포인터 증가 연산은 줄일수 없고 비교연산만 줄일 수 있다)
꼭 8로 나눌 필요는 없으며, 이는 적절히 조정하면 된다. Duff는 캐시 사이즈를 고려해서 8 정도로 결정한 것 같다. 루프를 많이 풀어 쓸수록 더 많은 코드가 생성이되고 함수 크기가 커지게 될 것이다.

그런데 루프를 풀어서 쓰기 위해서 왜 꼭 switch 문을 사용한 것일까.
for(int i = 0; i < 100; i =+ 8)
{
    *a = *b++;
    *a = *b++;
    *a = *b++;
    *a = *b++;
    *a = *b++;
    *a = *b++;
    *a = *b++;
    *a = *b++;
}
위처럼 루프를 풀어내는 것도 물론 가능하다. 그런데 숫자가 딱 나누어 떨어지지 않으면(위 예에서는 100 / 8) 나머지 처리를 밑에서 한번 더 해주어야 한다. Duff의 코드에서는 n을 (count + 7) / 8 로 정하고 case 구문의 숫자 위치를 적절히 배열하여 나머지 처리를 안해도 되도록 한 것이 중요한 포인트이다. 이렇게 하면 한방에 깔끔하게 처리할 수 있고 따라서 텍스트의 크기도 약간 더 작아진다. 사실 이 포인트가 C언어의 문법으로 범용적인 loop unrolling을 구현가능하게 하는 것이며 Duff's Device라고 불리는 아이디어이다.

그런데 요즘 우리가 쓰는 거의 대부분의 컴파일러들은 최적화를 위해 loop unwinding을 지원하고 있으며, 손으로 루프를 풀어서 쓴 것보다 더 효율적으로 코드를 생성해준다. 오히려 그런 손으로 풀어쓴 루프가 컴파일러의 최적화를 방해해서 더 느린 코드가 생성될 수도 있다. 보기에 안좋은 것은 말할 필요도 없다.
이것은 이미 어딘가에 사용되고 있는 Duff's Device와 같은 코드들을 보통의 코드로 변경함으로서 오히려 더 빠른 성능을 얻을 수도 있다는 뜻이고 따라서 이런 루프 풀기를 적용하려고 할 때에는 정말 도움이 될지 미리 벤치마크를 잘 해봐야 한다. 만약 벤치마크 해보는 것이 귀찮다면 루프 풀기가 아닌 보통의 코드를 사용하는 쪽으로 베팅하는 것이 심신에도 좋고 동료들과의 관계에도 이로울 것이라 확신한다.

_countof 매크로

2011. 3. 15. 06:48 | Programming

'Programming' 카테고리의 다른 글

윈도우 드라이버를 만들 때 알아야 할 기초적인 내용들  (2) 2011.05.23
Duff's Device  (0) 2011.04.07
FIELD_OFFSET 매크로  (1) 2011.03.01
PAGED_CODE 매크로  (6) 2011.02.27
디렉터리의 읽기 전용 속성  (4) 2011.02.20