4일차 강좌를 시작하기 전에..

워.. 거의 3주만에 작성하는 강좌입니다..

요새 시간이 엄청 빠르게 지나가는군요..

이것저것 일도 꽤 있고, 여러사람 만나는 중이라서요..

그래도, 시간을 내어 강의를 작성해 봅니다..

 

Stdio? Stdlib? 일단 화면에 뭐가 보여야 말이지..

일단, 전의 강좌에서 나오던게 있었죠?

맨 앞에 거의 무조건 등장하던것..

#include <stdio.h>

이런것 말이에요..

그리고 printf(어쭈구리저쭈구리); 요런것도 나왔지요?

일단 작성해 보신분들은 아시겠지만 printf란 놈이 화면에 뭔가 뿌려주는놈이라는걸 눈치채셨을겁니다.

맞습니다. 화면에 뭔가 뿌려주는놈이죠..

 

그전에 함수란 녀석에 대해 알아봅시다.

함수가 뭘까요?

한마디로,

“뭘 집어느믄 뭘 뱉는 놈입니다.”

 

일단, 어느 실행프로그램이건간에, main() 함수는 꼭 있습니다.

함수중에 그게 없으면 라이브러리라고 부르지요.

 

그리고 매우 기본적인건데..

{ } 요거는 안에 들어있는걸 하나의 프로세스로 생각하자는거죠..

 

자, 이제 c 프로그램은 웬만큼 다 보고 뭐하는놈인지 들여다 볼수 있게 되었습니다 ^^

 

그런데 아직까지 #include에 대해서 이야기를 안 했다고요?

include가 한국어로 뭐죠?

네. 맞습니다. 포함이라는 뜻이죠..

 

사실 printf같은 함수의 경우 ‘만들어진 함수’입니다.

원래 c 컴파일러에 내장되어 있는게 아니에요!

리눅스의 경우 glibc라는 함수의 모임에 있는겁니다.

 

뭐, 그걸 갖다 쓰는겁니다.

그럼 뭘 갖다 쓰는걸까요?

stdio라는걸 갖다 쓰네요?

stdio를 보고 스튜디오라고 생각하신 분이 계시다면..

그렇게 생각하셔도 좋습니다..

뭐, 그래도 제대로 알려드리는게 좋겠지요?

이런 기본은 찾아보면 맨날 나옵니다. 지겨워요 ㅋㅋ

std는 standard의 축약이고,

io는 input, output의 축약입니다.

그러니까, 말 그대로 표준 입출력 라이브러리지요.

 

그냥 키보드 입력받고, 화면에 텍스트 출력해주는, 매우 기본적인 입출력에 대한 라이브러리이죠.

아니, 왜 그래픽부터 시작 안 하냐고요?

에이.. 방정식도 모르는데 미적분 하려고요? 뭐 할수도 있겠져..

그런게 가능한 천재라면 왜 제 강좌를 보고 있는거죠?

 

여담이지만, 요즘은 정말 방대한 라이브러리 안에서 살고 있습니다..

컴퓨터 프로그래밍의 꽃은 자료구조라고 생각하는데..

실제로 그 꽃으로, STL(Standard Template Library)이 있지요..

그걸 보고 있자면.. 정말 사람이 생각할 수 있는건 다 불태워서 생각했다고 생각합니다..

그래픽 라이브러리라던가, 3D 라이브러리..

돈을 주고 사야 하는 상용 라이브러리..

정말 웬만한건 라이브러리가 다 있습니다..

그걸 가져다 쓰면 되는거지만..

알아야 갖다 쓰죠?

 

뭐, 저는 항상 이야기합니다만, 기본이 가장 중요합니다.

 

하는김에 코드랑 헤더랑 왜 분리해야 하는지도 좀..

지금 오픈소스쪽 프로그램들은 사실, 분리를 하지 않아도 별 관계는 없을듯 싶기도 하고..

굳이 분리를 해야 하나? 라는 생각을 하시는 분들도 상당히 많습니다만..

아무래도 헤더와 프로그램은 분리하는게 편하지요.

 

일단, 헤더와 프로그램을 분리하게 되면..

헤더에 함수가 하는 일과 주어야 하는 인수에 대한 설명만 주석을 달아주고, (사람이) 헤더의 내용만 가지고 라이브러리가 무슨 일을 하는지 알아보기가 쉽다는거죠..

아니면, 공개를 하는데 소스코드는 웬지 주고싶지 않다고 생각할 때, 헤더파일만 공개하면 되니까 코드 보호가 되기도 합니다..

실제 기업에서 라이브러리를 오픈할때 많이 이용하는 방식이죠..

 

굳이 헤더와 소스를 구분해야 할 필요가 없다고 느끼시면 i dont care. 별로 상관은 안 하겠습니다만..

(실제로 저도 짧은 프로그램을 작성할 경우 헤더를 작성하지 않습니다.. 블럭쌓기도 얼마나 분리를 할지는 잘 모르겠어요 ^^;)

많은 분들이 분리를 이용한다는건, 뭔가 편해서 그럴 가능성이 매우 높지요..

 

지금 당장은 헤더분리에 대해서 모든 곳에 적용하려고 생각하진 않으셔도 별 상관은 없습니다만,

나중에 필요할 경우 쉽게 적응할 수 있을 정도로만 알아두시면 될것입니다.

사실, 뭐 어려운것도 아니고요.

 

int sum(int a, int b) {

  int tmp_sum;

  tmp_sum=a+b;

  return(tmp_sum);

}

이런 함수를 작성하였다고 할 때,

 

int sum(int a, int b);

이런식으로 함수와 인수만 헤더로 분리할 수가 있지요.

 

이게 처음에 조금 있을때는 별로 크게 신경쓰이진 않는데, 프로그램 덩치가 좀 커지면 ‘아 왜 사람들이 헤더랑 소스랑 분리하는지 알겠다’라고 생각이 드실겁니다..

 

 

그럼 또 빠른 시일 내에 5일차 강의를 들고 찾아뵙겠습니다..

신고
  1. alisol 2011.09.19 16:29 신고

    잘 봤습니다

3일차 강좌를 시작하기 전에..

드디어 가장 중요한 부분을 이야기해야 할때가 왔군요..

그런데 마음이 다른곳에 가있습니다.. 죄송합니다 ?_-;

제가 mv2530이라는 mp2530 기반의 magiceyes 기판을 가지고 있는데..

갑자기 가지고 놀고 싶어져서 말입니다..

아, 오늘 강의가 20일짜리 강의중에서 가장 중요한 부분인데..

어쨌거나 시작하도록 하겠습니다.

 

StarUML로 플로우-차트를 한번 만들어 봅시다. 제일 중요한 시간이에요.

하하.. StarUML을 이용하려 했습니다만..

DIA라는 툴이 범용성면에서 훨씬 좋습니다..

StarUML의 경우는 Class 기반의 어플리케이션 작성에 많은 도움이 됩니다..

물론 Microsoft Office 제품군의 Visio라는것도 있습니다만, 강좌는 DIA로 진행하도록 하겠습니다.

그 DIA라는 놈은 http://live.gnome.org/Dia/Download <- 요기서 받으실 수 있습니다.

실행을 하시면 대충 그래픽 프로그램같은 화면이 나옵니다..

네.

그렇습니다. 우리는 그림을 그릴것입니다.

지금 제가 툴을 설명하고 있습니다만, 사실 가장 좋은 방법은 펜과 종이를 가지고 그려보는 것입니다.

다른 분들은 어떨지 모르겠습니다만, 저는 그림부터 그립니다.

특히, 많은 분들과 협업이 이루어질 경우 가장 좋은 방법입니다.

다들 자기가 다루는 언어가 있고, 실력차이도 있습니다만..

이 flow-chart라는 놈은 우리가 쓰는 언어로 치자면 바디랭귀지입니다.

프로그래밍 언어를 전혀 모르는 사람도 대화에 참여할 수 있을 정도니까요.

이미 만든 프로그램에 아무리 주석을 입힌다 한들, 플로우챠트보다 알아보기 쉬울리는 없을겁니다.

하지만 이상하게도 각 도형의 의미는 옛날것들을 많이 쓰는듯 싶습니다..

 

그래도 기본적인 도형과 의미를 알아보도록 하지요.

Array : 처리

어떤 계산을 하거나 눈에 보이지 않는 처리를 할 때 쓰입니다.

 

Array : 입출력

데이터의 입출력시 씁니다. 근데 전 잘 안 씁니다(!?).

 

Array : 조건분기

조건문입니다. 그러니까, 프로그램이라면 이걸로 모든게 이루어진다고 봐도 과언이 아니지요.

 

Array : 연결자

그러니까, 공간이 부족할 때 씁니다.

어디로 가라.. 뭐 그런거죠..

제경우 페이지 넘김 아이콘보다는 아예 이걸로 통일해버립니다..

 

Array : 화면으로 표시

모양이.. 일단 옛날 TV나 CRT 모니터처럼 생겼지요?

근데 저는 이것도 잘 안 씁니다..

 

Array : 온라인 기억장치

온라인 보조기억장치.. 라고 합니다.

전 지금까지 순서도에서 이 도형을 써본적이 없군요.. ?_-;;

 

Array : 페이지 넘김

제경우 초창기에 몇번 사용했습니다만, 지금은 거의 사용해본적이 없군요..

 

Array : 출력

출력장치로 출력하는걸 말합니다.

종이를 찢은것 같은 모양이지요?

원래는 프린터로 출력하는 용도로 많이들 사용했었을 겁니다.

하지만 저는 모든 출력에 이 도형을 사용합니다..

 

Array : 수작업

오프라인으로 수작업해서 때려넣는다.. 뭐 그런쪽으로 많이 사용하는듯 싶습니다..

프로그래밍에서 자주 사용하지는 않는듯 싶군요..

 

Array : 준비

배열의 선언을 한다던가 하는 의미로 많이 사용됩니다.

의외로 제가 웬만하면 사용하는 도형입니다.

 

Array : 입력

도형을 보시면 키보드처럼 생겼지요?

아니라구요? 아. 비싼 키보드 안 쓰시는군요.

비싼 키보드는 저렇게 생겼습니다.

제 경우는 입력을 모두 저 도형으로 처리합니다.

 

Array : 프로시저

제 경우 보통 함수라던가.. 어쨌든 함축의 의미로 많이 사용했던것 같습니다.

 

Array : 터미널

음.. 그러니까.. 시작과 끝을 알리는 도형입니다.

보통 처음과 끝에 하나씩 들어가죠.

요걸 그리면 순서도 반은 그린겁니다.

시작이 반이잖아요?

 

Array : 디스크

디스크 입출력시 사용합니다.

 

 

… 으음.. 뭐 넘어간것도 있고 설명 안한것도 있군요.

반복문의 경우인데, 박스안에 집어넣어두는 식으로 많이들 활용합니다.

 

그럼, 아주 기본적으로 블럭쌓기의 개념을 그림 안에 담아보도록 하겠습니다.

Array

 

웬지 허접하고 너무 간단해 보이나요?

처음은 이정도면 됩니다.

(사실 나중 되어도 그림 그리는 스킬이 올라가진 않을겁니다)

원래는 그냥 종이에 스케치 하는 정도니까요.

 

단지 그냥 어떻게 돌아가는지 감이 오지 않을때 이런식으로 그림을 그리다 보면 어느새 이미 세부사항을 작성하고 있는 자신을 보게 될것입니다.

 

이건 정말 한번씩 해보시기 바랍니다.

다른건 직접 해보지 않으셔도 되지만, 이건 최소 한번은 그려보십시오.

 

가장 중요한 3일차 강좌는 이것으로 마치겠습니다.

신고
  1. alisol 2011.09.01 17:01 신고

    우분투 소프트웨어 센터에 Dia Diagram Editor 를 찾았습니다. 소스포지에 있는 것을 내려받아 설치하려다가 알게되었습니다

2일차 강좌를 시작하기 전에..

아.. 오랜만입니다.. 거의 일주일만인가요?

정말 정신없이 살고 있는것 같습니다..

정신도 없고 시간도 없고 돈도 없군요.. 최악입니다 ㅋㅋ

하지만 2차 강의자료까지는 완료를 지어야 저는 제 나름대로, 강좌를 보시는분 나름대로 매듭을 지을 수 있을테니까요..

솔직히 말씀드리자면 저도 잘 모르면서 강좌를 진행하는 중입니다.

1일차때 이미 말씀드렸지만, 지금 강좌를 진행하는 내용은 다른 강좌내용을 보고 정리하는 내용이 아니고 직접 작성하는겁니다..

물론 다른 훌륭한 오픈 강좌들이 많습니다만, 1차 강좌는 제 자신에 대한 매너리즘 극복의 의미가 더 큽니다..

사실 오늘 강좌는 별건 없지만 중요한 내용중의 하나입니다.

자, 시작하죠..

 

플랫폼 인디펜던스 프로그램은 뭐임?

Platform Independance, 즉 플랫폼에 의존적이지 않은 프로그램을 말합니다..

대표적인 플랫폼 인디펜던스 프로그램은 거의 대부분 오픈소스입니다..

플랫폼의 범위를 어떻게 설정하느냐에 따라 달라질 수는 있습니다만,

(특히 요즘들어 모바일까지로 범위를 설정하는 경우도 있는듯 싶습니다)

제가 볼때는 설계가 잘 된 프로그램이면 어디에서든 돌릴 수 있다고 봅니다..

 

멀티플랫폼이나 크로스 플랫폼이라고 이야기하기도 합니다..

사실 멀티플랫폼이라는 말이 더 많이 쓰입니다..

완벽한 플랫폼 비의존이라는건 있을수가 없는 일이니.. ^^;

 

그럼 대충 뭐가 있는지 한번 볼까요?

 

예전 trolltech라는 이름을 가지고 있던 회사가 있습니다..

현재는 nokia社로 인수되었는데, 그 회사에서 만든 qt라는 ui kit1가 있는데, c++로 이루어져 있습니다..

플랫폼 인디펜던스라고 하면 대표적일수 있지요..

물론 Sun Microsystems社(현재는 Oracle社에 합병되었습니다)의 java도 플랫폼에 비의존적이라고 할 수 있을 정도입니다..

Macromedia社(현재 Adobe社에 합병되었지요)의 Flash는 논란이 많긴 합니다만, 플랫폼 비의존이라고 말할 수 있을 정도입니다..

음.. 설명하다보니 웬지 없어진 회사들의 서비스만 적어놓은것 같군요 Array

뭐, 지금까지의 오픈소스로 보시면 될것입니다.. 非오픈소스인 거대기업이 오픈소스를 그만큼 두려워한다는 반증이니까요..

(아, 물론 오픈소스 == 플랫폼 비의존은 아닙니다만, 둘은 굉장히 깊은 상관관계가 있습니다)

 

웹쪽으로는, 웬지 전쟁입니다..

일단, Mozilla 재단의 Firefox Browser가 대표적인 멀티플랫폼이지요.

Opera Software社의 Opera Browser 역시 플랫폼 상관안하고 돌아가지요..

Google社의 Chrome Browser를 빼먹으면 또 섭하겠지요?

그리고 서버로는 apache group의 apache http 서버가 있습니다..

어느정도 제한이 있긴 합니다만, 웬만한곳에는 다 돌아갑니다..

사실, 오픈소스 OS가 퍼지는 원동력은 웹이라고 해도 과언이 아닐 정도입니다..

 

 

그외에도 많은 오픈소스 프로그램들은 플랫폼에 상관없이 돌아가는듯 싶습니다..

그 이유는 아무래도, 소스가 오픈이 되어있다보니 새로운 플랫폼에 돌릴거라면 거기에 맞춰 새로 컴파일하면 되니까요 Array

 

사실, 대부분의 멀티플랫폼 어플리케이션들은 “*nix에서 돌아가는가?” 가 관건이 되지요.

GNU Project를 비롯하여 *nix 플랫폼에서 돌아가는 대부분의 어플리케이션들은 맥이나 윈도우에서 거의 무조건 돌아간다고 봐야겠지요.

 

제가 강좌를 gcc로 진행하는 이유는, 언제 어디서나 장소에 구애받지 않고 코드를 수정할 수 있고, 어느 플랫폼이건 간에 돌리면 돌아가는 코드를 짜는게 어렵지 않다는걸 보이기 위해서지요.

 

뭐 사실 웹이건 어플리케이션이건 표준을 따라가면 작성할 코드의 양은 상당히 줄어듭니다.

 

 

플랫폼 인디펜던스 프로그램은 어떻게 작성할까?

거창한것처럼 말했지만 사실, 별것 없습니다..

UI나 멀티쓰레딩, 시간과 같은, OS에 의존적인 부분만 분기하여 작성하면 됩니다.

아예 QT의 스타일을 따라가는 방법도 있겠습니다만, 바로 따라가기는 힘들 정도로 방대합니다..

물론 QT 스타일을 따라가면서 C++쪽으로 언어 성향을 따라가는것이 최고겠습니다만..

강좌를 진행하는데 있어서 곁다리로 설명해야 될 것이 산더미가 되어버립니다..

그쪽은 아예 레퍼런스 서적을 참조하는 편이 이득입니다..

 

그럼 모두의 친구 Hello World를 플랫폼별로 만들어 볼까요?

#include <stdio.h>
 
enum Modes { Release = 0, Debug };
enum Platforms { Other, Windows, Apple, Linux };
const char* PlatformStr[] = { "Other Platform", "Windows", "Apple", "Linux" };
 
int main()
{
  enum Platforms platform = Other;
  enum Modes mode = Release;
#ifdef _DEBUG   
  mode=Debug;
#endif
#ifdef _WIN32   
  platform=Windows;
#endif
#ifdef __APPLE__
  platform=Apple;
#endif
#ifdef __linux__
  platform=Linux;
#endif
  if(mode) printf("Debug Mode : ");
  printf("Hello, %s\n", PlatformStr[platform]);
  return(0);
}

 

단지, 분기를 좀 넣으면 되는것 뿐입니다..

그냥 OS별로 신경쓴다고 생각하면 되지요..

 

좀더 분기를 넣어보고 싶었습니다만, 긴 소스는 짜증나잖아요. 그쵸?

 

자 2일차는 여기까지만 하지요.

 

 

 

초반 강의가 짧다고 계속 짧을거라 생각하지 않으시는게 좋을거에요 Array

신고
  1. alisol 2011.08.31 16:53 신고

    컴파일~ 플리즈~ 방법이 궁금합니다.

  2. Drake 2011.09.10 21:57 신고

    컴파일하는 방법은만약 foo.c 라고 작성을 하셨다면gcc -o bar foo.c요렇게 하시면 foo.c를 컴파일해서 bar라는 파일을 만들어 냅니다.아무런 메세지가 나오지 않으면 컴파일 성공입니다.실행방법은 ./bar 라고 하시면 됩니다.

  3. alisol 2011.09.19 17:34 신고

    그러고 보니 제가 분기란 뜻을 잘 모르겠습니다.

  4. Drake 2011.09.23 07:46 신고

    음.. 네이버사전 링크합니다..http://hanja.naver.com/word?q=%E5%88%86%E5%B2%90국어사전에 없는걸 보니 아무래도 제가 어렸을적 일본책의 번역본이었던듯 싶군요..무튼 뜻은 그렇습니다.

일단.. 강좌 들어가기 전에..

전 사실 동영상 강의라던가 그런걸 많이 보질 않아서 지루하게 강좌를 이끌어갈듯 합니다만, 이것은 차차 나아질거라 생각합니다.

첫 강의는 완벽하게 독단적으로 할 생각입니다.

원칙적으로 제 강의를 가져다가 이름만 바꿔서 자기가 썼다고 구라를 치시건 뭘 하건 그닥 상관은 없습니다.

프로그래밍 언어를 제가 만든것도 아니고.. 이런 지식 정도야 인터넷 좀 뒤지면 어디서든 나오는거니까요..

그렇다고 라이센스를 포기한건 아닙니다.. 하지만 제가 어떻게 막을 수 있는 방법이 있는것도 아니고요.

뭐 막 퍼가시더라도 한가지 부탁이 있다면, 퍼가실땐 끝까지 퍼가시라는겁니다.

비록 제가 엄청난 고수는 아닐지라도 이것저것  물어보면 굉장히 곤란한 질문(EX: 네이트온 해킹이 가능한가 등) 이외에는 답변을 해드릴수는 있습니다.

저도 피드백 받는거 좋아하는데 독자와의 소통을 가져가놓고 꿀먹은 벙어리가 되면 진짜 좀 거시기하잖아요.

 

강사는 뭐하는 사람임?

현재 32살 미혼의 NEET족1 입니다.

 

컴퓨터라는걸 처음 만져본건 1987년도에 SPC-15002과 대우 MSX2+3로 시작했었지요..

Z80 프로세서4를 탑재한 8비트 컴퓨터였지요..

저는 1세대 사이언스키드였습니다.. 8살부터 A-Basic5 가지고 놀았지요..

11살때 경진대회에서 수상을 하기도 했었습니다..

이후 16비트 시절로 들어서면서 Borland社6의 컴파일러를 가지고 놀았지요..

Turbo C - Turbo Assembler - Turbo Pascal 순으로 성향이 변화되어 갔지요..

TASM을 쓸때는 Softice7같은것도 만지고 놀았었습니다..

하지만 한국의 英才들이 다들 그러하듯 거기서 끝났습니다..

20대 시절에는 방문판매도 해보고.. 피씨방 알바도 해보고.. 건설현장 노가다도 해보고.. 공장에도 들어가보고.. 스키장 알바도 해보고.. 영어권 지역에서 사업실패도 해보고 뭐.. 그렇게 시간을 보내다 보니 벌써 30대가 되어버렸군요..

 

사실, 할 줄 아는것도 많고 이것저것 경험은 많지만.. 자의건 타의건 한군데에 진득하게 붙어있지를 못해서 이렇게 된것 같군요..

웹마스터나 웹프로그래머가 될 기회는 상당히 많이 있었는데, 그쪽으로 가기는 싫어서 거절하다보니 이렇게 되어버렸습니다..

 

강좌를 시작하게 된 것은, 솔직히 말해서 제 자신을 시험해보고 싶었기 때문이죠.

프로그래머의 특성상, 자신의 실력을 정확히 보여주기 어려운 법입니다.

어쨌거나 프로그래밍 공부하는 친구들에게 가이드라인 제시를 해 줄수 있으면서 또 제 실력도 보여줄 수 있을거라 생각해서 진행을 하기로 마음먹었습니다.

 

불쌍하니까 제게 취업을 시켜줘야겠다 생각하시는 분들도 계실지 모르겠습니다만, 최소한 2차 강좌와 라이브러리 공개 후에 취업활동을 시작하거나 할 예정입니다.

 

리눅스는 뭐임?

뭐, 오픈소스 OS입니다..

사실 호불호가 많이 갈리는 쪽이고, 저도 굳이 윈도우나 맥 사용자에게 리눅스를 강제하고 싶은 마음은 없습니다..

하지만 기본기를 다지기에는 가장 좋은 환경이라고 판단합니다.

리눅스 기반으로 강의를 진행은 합니다만, 윈도우에서도 VS8로 컴파일 할 수 있도록 진행합니다..

 

리눅스가 퍼지기 시작한건 최근의 일입니다만, 그 전신인 유닉스가 만들어진 시기는 1969년도입니다..

Only C로 포팅이 된건 1973년도구요..

물론 그때랑 지금이랑은 많이 다르긴 하지만, 기본 베이스는 크게 바뀐건 없습니다..

리눅스는 1991년도에 GNU9에서 공개가 된 OS입니다..

 

좀더 이야기를 삼천포로 빠뜨려보자면, 당시에 한국통신10에서 그게 공개되기 1년전인 1990년도에 전화요금에 시분제11를 도입했는데(그게 한국통신이 잘못된거라고 보기는 힘들지만요), 그때문에 PC통신12이 위축되었죠..

뭐, 당시에 그게 아니었으면 한국에서도 상당히 많은 사람들이 GNU의 공헌자가 되었을지도 모르겠습니다..

 

뭐 다시 본론으로 돌아간다고 해도 이야기가 삼천포로 많이 빠져있는것 같네요..

어쨌거나 GCC13라는 컴파일러는 대다수의 사람들이 안정적으로 평가하고 있고, 대단히 잘 만들어진 컴파일러지요.

C로 만들어진 C 컴파일러입니다.

이후 강좌를 진행하는게.., 기본은 C에 대해 설명합니다만 최종 코드는 C++14입니다..

이건 제가 선택한 언어일 뿐이며, 여러분은 자기 자신에게 맞는 언어를 찾으면 될것입니다.

 

제가 베이스로 리눅스 OS를 선택한 이유는 다음 강좌에서 좀더 설명을 드리도록 하겠습니다.

 

SSH는 뭐임?

Secure SHell의 약자구요..

보안 네트워크를 이용하여 서버에 접속하는걸 뜻합니다..

기본적으로 텍스트 모드입니다만.. 초기에 짤 프로그램은 텍스트니까 괜찮습니다..

실제 강좌를 진행할 때에는 학원에서 진행을 하게 되는데, 굳이 리눅스를 설치하지 않아도 ssh 접속프로그램만 있으면 인터넷이 되는 어디에서든 프로그래밍을 할 수 있게 되지요.

 

계정 만들어줌?

오프라인으로 뵌 분이면 만들어 드릴수 있습니다.

다시 한번 말씀드리지만 강좌는 원래 학원에서 강의를 할 예정이었으므로, 학원생에게는 학원쪽 서버를 이용할 생각입니다.

 

 

1일차는 여기까지입니다..

적어놓고 보니 별 내용이 없어보이네요..

아~ 앞으로도 이러면 안되는데..

곧 2일차 강좌로 또 찾아뵙겠습니다 ^^

 

 

 

1. Not currently engaged in Education, Employment or Training의 약자로 청년 무직자를 뜻합니다 ^^;

2. 삼성전자에서 만든 8비트 퍼스널컴퓨터

3. 대우전자에서 만든 8비트 퍼스널컴퓨터

4. 자일로그 Z80이라는 프로세서로 2.5MHz의 속도였습니다. 지금은 3GHz정도 속도니까.. 단순 속도만 해도 1000배 이상의 차이가 있습니다..

5. 마이크로소프트 베이직의 개량버전인 MSX Basic의 OEM이었던 것으로 기억합니다. 당시에는 컴퓨터를 켜면 도스나 윈도우같은게 아니라 프로그래밍 언어가 OS같은 기능을 했었습니다..

6. 당시 최고의 프로그래밍 언어 개발회사였지요.. 지금은 Embacadero라는 회사에 인수합병이 되었습니다.

7. 당시 최고의 디버거였습니다. 리버스 엔지니어링.. 그러니까 크래킹을 하기 위한 용도로 많이 사용되었던 프로그램입니다.

8. Visual Studio. 마이크로소프트에서 만든 통합 개발 환경입니다. 개인적으로는 굉장히 잘 만들었다고 봅니다.

9. GNU’s Not Unix로 리차드 스톨만이라는 교주(사람보다는 교주라는 단어가 더 잘 맞는듯 합니다)가 당시 엄청나게 비쌌던(가장 싼게 600달러급이었습니다. 80년대 초반에 600달러입니다) Unix를 아예 자유소프트웨어로 만들자고 주장하면서 엄청난 사람들이 동참하게 되었지요.

10. 현재 KT죠. Korea Telecom.

11. 전화요금이 원래는 통화당 30원이었는데 시분제라는걸 시행하면서 3분당 30원이 되었죠..

12. 지금은 인터넷이지만 당시에는 전화를 걸어서 그것으로 통신을 하는, 전화기를 이용한 통신이 주류를 이루었습니다.. 속도는.. 2400bps.. 그러니까 초당 2400비트, 지금 인터넷은 일반적으로 100Mbps.. 그러니까 초당 1억비트.. 근데 슬슬 기가비트 인터넷이 대중화되려고 하죠?

13. GNU C Compiler의 약자입니다. 대부분의 리눅스에는 기본으로 설치가 되어 있거나 매우 쉽게 설치할 수 있도록 되어 있지요.

14. C의 개량 버전이라고 생각할 수 있을듯 합니다.

신고
  1. 비밀 2011.06.01 16:36 신고

    관리자도 볼 수 있는 비밀 댓글입니다.

  2. cartes 2011.06.01 20:14 신고

    잘읽고 갑니다..^^..-cartes

  3. alisol 2011.08.31 16:21 신고

    정주행 시작합니다~ ~

Source : http://i7dayz.egloos.com/1093041

 

 

서론

C Language를 공부하면서 가장 이해하기 어려운 것이 무어냐고 물어본다면,

아마도 거의 대부분 "바로 포인터(Pointer)라는 녀석이다!" 라고 말할 것입니다.

C에서 다른 건 다 이해가 되어도 "포인터 만큼은 죽어도 모르겠다" 라고 말하는 경우를 제 주변에서도 심심치 않게 봐왔습니다.

사실 C는 어려울 수밖에 없습니다.

C를 그저 프로그래밍의 기초 과정에서 배우는 옛날 언어라고 생각하고 가볍게 볼만큼 만만한 녀석이 전혀 아닙니다.

C는 어셈블리(Assembly)의 사촌입니다.

다시 말하면, C는 하드웨어 - 특히 마이크로프로세서(CPU)와 친한 녀석입니다.

때문에 하드웨어에 대한 기반 지식없이는 C를 제대로 이해할 수가 없습니다.

포인터라는 녀석이 특히 그렇습니다.

C를 강력하게 만드는 무기가 바로 포인터라고 흔히 말하지만,

이걸 이해하는 것은 왜 그리 어려운 걸까요.

조엘('조엘 온 소프트웨어'의 저자)은 이 '포인터'의 개념을 이해하는 게 '그냥 불가능'한 인간이 있다고 말합니다만, 저는 절대로 이해 불가능한 것이 아니라고 굳게 믿습니다.

제가 여기서 그것을 감히 증명해 보려고 합니다.

일단 기초의 기초부터 들어갑니다.

아주 유치할 정도로 기초부터 다시 설명하겠습니다.

1. 메모리(Memory)와 어드레스(Address)

일단 포인터의 동작은 전부 메모리(Memory)와 관련이 있습니다.

따라서 우리는 먼저 메모리에 대해서 알아야 합니다.

폰 노이만 구조(프로그램 내장 방식)를 따르는 현대의 모든 컴퓨터들은 기본적으로 모든 것이 주기억장치 - '메모리'에 올라가야 CPU가 실행을 시킬 수 있습니다.

프로그램 수행 코드도 메모리에 올라가고, 그에 필요한 데이터 역시 메모리에 올라갑니다.

일단 여기서 우리는 '데이터'에 관심을 가져보기로 합니다.

'100' 이라는 숫자가 메모리에 올려졌다고 해보죠.

그러면 메모리의 어딘가에 이런식으로 데이터가 저장이 될겁니다.

─┬───┬───┬───┬─

…│100│ │ │…

─┴───┴───┴───┴─

이제 메모리에 저장된 '100'이란 숫자를 꺼내오려고(읽어오려고) 합니다.

그런데 문제는 이 100이란 숫자가 드넓은 메모리 영역의 어디에 존재하는지 알아야 한다는 겁니다.

그래서 데이터가 저장되는 메모리 공간에는 일종의 일련번호가 부여되어 있습니다.

그것을 메모리의 주소 - 어드레스(Address)라고 부릅니다.

메모리는 기본적으로 바이트(Byte = 8bit) 단위로 데이터가 저장되기 때문에,

하나의 어드레스는 메모리 상의 하나의 바이트 공간과 대응됩니다.

이 말이 이해가 안된다면, C에서의 배열(Array)을 연상하면 되겠습니다.

   int A[10];

이렇게 하면 C에서는 10개의 정수(int) 데이터를 저장하는 배열이 만들어집니다.

이것은 마치 10개의 int형 변수를 하나로 묶어서 다루는 것과 같습니다.

배열의 각 공각에 데이터를 기억시키기 위해서는 이렇게 하죠.

   A[0] = 100;

   A[1] = 200;

   A[2] = 300;

   ...

   A[9] = 1000;

이때 [ ]안에 넣는 숫자, 이것은 곳 배열에서 어느 영역을 지칭하는 '번호'인 셈인데,

이것을 메모리의 관점으로 바꿔보면...

메모리 전체가 하나의 거대한 배열이라고 가정하면,

이 거대 배열의 각 영역에 접근하기 위한 '번호'가 필하요게 되고,

바로 이것이 주소(Address)라는 것으로 보면 됩니다.

2. 변수

우리가 C 코드를 만들때, main() 함수를 작성하면서 가장 먼저하는 일이 무엇입니까?

────────────────────────────────────────

void main()

   {

int a, b;

      ...

   }

────────────────────────────────────────

바로 변수를 선언하는 거죠.

바로 이 선언이라는 것은, 자신이 사용할 메모리 공간을 예약하는 것입니다.

─┬───┬───┬───┬─

…│ a │ b │ │…

─┴───┴───┴───┴─

그럼 예약도 되었겠다, 값을 써보도록 하죠.

   a = 10;

   b = 20;

─┬───┬───┬───┬─

…│ 10│ 20│ │…

─┴───┴───┴───┴─

그럼 이번엔 a, b의 값을 한번 출력해 봅니다.

   printf("%d %d", a, b);

   [결과]

   10 20

C에서는 이처럼 변수 이름을 통해서 메모리에 값을 읽고 쓸 수가 있습니다.

이 당연한 걸 왜 새삼스레 다시 설명하냐고 태클이 들어올 것 같습니다만, 잠시 참아주세요.

앞서 메모리 상의 데이터는 '어드레스'를 통해서 접근할 수 있다고 얘기했습니다.

C에서 변수는 메모리의 한 부분입니다.

그런데 C에서는 '변수 이름'을 가지고 접근하고 있군요.

바로 이 '변수 이름'이라는 것은 메모리 어드레스를 추상화시킨 것입니다.

실제 C에서는 변수앞에 '&' 연산자를 붙여서 그 변수의 어드레스를 바로 얻을 수 있습니다.

────────────────────────────────────────

#include <stdio.h>

void main()

   {

int a, b;

      a = 10;

      b = 20;

      printf("Address: %d %d\n", &a, &b);

   }

   [결과]

clip_image001

────────────────────────────────────────

이 결과를 잘 보면, a와 b의 어드레스에는 4만큼의 차이가 있습니다.

이것은 둘다 int형(정수형)이고, 일반적으로 32bit CPU에서 정수는 4byte의 크기를 같습니다.

그리고 두 변수가 나란히 선언되었기 때문에, 이 둘은 메모리상에서도 연속해서 공간을 차지하게 됩니다.

참고로 x86 계열의 CPU는 어드레스가 높은 쪽에서 낮은쪽으로 채워집니다.

때문에 먼저 선언된 쪽이 높은 주소값을 가지게 됩니다.

3. 데이터와 타입

기본상식이지만, 컴퓨터에서는 모든 데이터는 2진수(Binary)로 표현됩니다.

이말은 즉, 그 어떤 종류의 데이터라할지라고 메모리에 저장될 때는 2진수로 기록된다고도 할 수 있습니다.

clip_image002

그럼 반대로, 메모리에 저장된 데이터를 읽어 올때도 역시, 이것을 "문자열"로도 "정수"로도 "실수"로도, 기타 얼마든지 다른 형식으로 읽어 들일 수 있다는 것이 됩니다.

clip_image003

그렇다면, 메모리에 저장된 자료를 과연 어떤 형식(Type)으로 해석해야 하는지 문제가 됩니다.

그렇기 때문에 우리는 변수를 선언할 때, 반드시 그 변수가 취급하는 데이터형(Type)을 명시하게 됩니다.

int number;                // 정수형

float real_num;           // 실수형

double bigsize_real;  // 큰 실수형

char* string;             // 문자열

또한 이 데이터 타입은, 변수의 선언에 있어서, 그 변수에게 얼마만큼의 메모리 공간을 할당해야 하는가를 결정하는 정보이기도 합니다.

보통 int와 float은 4 Byte 크기를 할당받게 되고, double은 8Byte, 문자열의 경우에는 문자열의 길이에 따라 다릅니다.

4. 포인터

자, 이제 드디어 포인터에 대해 이야기할 차례입니다.

"포인터(Pointer)란 무엇인가?"

라고 묻는 다면, 그 정의는 간단합니다.

"메모리의 어드레스(Address)를 데이터로 취급하는 변수"

즉 포인터 변수에는 어드레스 값을 저장할 수 있습니다.

그래서 포인터 변수는 다음처럼 특정 변수의 어드레스를 기억하는 것이 가능합니다.

int V;

int *P;

   P = &V;

포인터 변수가 어느 변수의 주소(Address)값을 가지고 있는 상태.

이 상태를 우리는 포인터 변수 P가 일반 변수 V를 "가리키고 있다"라고 표현합니다.

clip_image004

앞서 메모리의 어드레스를 통해서 메모리에 있는 데이터에 접근할 수 있다고 했습니다.

변수 역시 자신이 어드레스를 가지고 있기 때문에, 우리가 변수를 통해서 데이터를 읽고 쓸수 있는 것입니다.

그렇다면, 포인터 변수가 데이터로서 가지고 있는 어드레스를 이용해서도 메모리에 접근 할 수 있지 않겠습니까?

clip_image005

변수 V가 가지고 있는 데이터에 접근 하려 한다고 하면, 보통은 변수 V를 직접 호출해서 바로 접근할 수 있습니다.

그런데 포인터 변수 P가 V를 가리키고 있는 상태에서는 포인터 변수 P를 통해서 간접적으로 V에 접근할 수도 있게 됩니다.

예를 들면,

   V = 10;

이렇게 V에 10 이란 상수를 바로 기록할 수도 있고,

  *P = 10;

이렇게 포인터 변수를 통해서 간접적으로 V에 10을 저장시킬 수도 있습니다.

여기서 포인터 변수 앞에 쓰인 '*' 연산자는 보통 "P가 가리키고 있는 변수의 값을 가져온다" 라고 말하는데, 사실 정확한 정의는"P가 가리키고 있는 곳=장소" 그 자체입니다.

간단히 말하면 '*' 연산자가 붙은 포인터 변수 = (*P) 자체가 하나의 변수처럼 취급될 수 있다는 겁니다.

따라서 아래처럼 값을 가져오는데도 쓸 수 있고,

  A = *P;

이처럼 값을 저장할 때도 쓸 수 있습니다.

  *P = A;

5. 포인터와 타입

C에서 포인터 변수를 선언은 이런식으로 하게됩니다.

int *p;

자 그럼, 이 p 라는 변수의 타입(Type)은 무엇일까요? 정수(int) 일까요 ??

잠깐 다른 문제를 내보겠습니다.

정수형(int) 변수의 타입(Type)은? → 정수(int)

실수형(float) 변수의 타입은? → 실수(float)

자, 그럼 포인터 변수의 타입은?

네, 당연히 포인터(Pointer)입니다.

int *ip;

float *fp;

double *dp;

char *cp;

void *vp;

이렇게 선언된 변수들은 죄다 '포인터' 형입니다.

결국 그 정체는 그저 '어드레스'를 저장하는 변수인 겁니다.

32bit CPU에서 이 어드레스는 32bit 정수(4 Byte)로 표현됩니다.

따라서 결국은 포인터 변수라는 건 int형 변수나 별반 다를게 없습니다.

단지 그 정수를 '어드레스'라고 해석할 뿐인 겁니다.

C에서는 변수 선언시에, 이름 앞에 '*' 라는 표시를 붙여서 이것이 포인터형 변수라고 컴파일러에게 알려줍니다.

그럼 * 앞에 있는 int 같은 타입 정보는 대체 무엇인가?

앞서 메모리에 저장된 데이터를 해석하려면 타입(Type) 정보가 필요하다고 했습니다.

포인터 변수의 타입은 포인터이니까, 포인터 변수의 데이터는 어드레스로 인식하면 됩니다.

그치만, 포인터 변수가 가리키는 곳(포인터 변수에 저장된 어드레스)에 있는 데이터는 어떻게 해석해야 하는가가 문제가 됩니다.

따라서 포인터 변수를 선언할 때는 두 가지 타입 정보가 필요합니다.

정확히 말하면, 포인터 변수가 가리키는 것에 대한 타입 정보가 추가로 필요해 지는 겁니다.

int *p;

이렇게 선언된 포인터 변수는 가리키는 대상이 정수(int) 타입이라는 것을 의미합니다.

앞서 '*' 가 붙은건 다 포인터형 변수라고 말했습니다만...

int *ip;

float *fp;

그 말대로라면 여기서의 ip와 fp는 같은 타입이라는 얘기가 됩니다.

그럼 이런 것도 가능할까요.

int a = 10;

int *ip;

float *fp;

   ip = &a;

   fp = ip;

마지막 문장 "fp = ip"에서는 ip가 가진 값이 변수 a에 대한 어드레스이므로, fp에는 a의 어드레스 값이 기록됩니다. "fp = &a"와 같은 결과가 되죠.

결론적으로 ip와 fp에 둘 다 같은 정수형 변수 a의 어드레스를 저장시켰습니다.

뭔가 불안해 보이는 코드이지만, 사실 이렇게 해도 컴파일은 됩니다.

다만 컴파일러는 정중하게 경고(warring) 메세지를 보냅니다.

   'int ' differs in levels of indirection from 'float *'

실수형 자료를 가리키는 포인터 fp에 정수형 변수의 어드레스를 할당시켰다는 거지요.

그래서 데이터를 잘못 해석해버릴 가능성이 있기 때문에 컴파일러가 경고를 보낸겁니다.

실제로 저렇게 사용하면 큰일(?)날 수 있습니다(...)

마무리

결론적으로 포인터라는 것은 메모리, 그 중에서도 '어드레스'를 다루는 테크닉입니다.

그렇기에 포인터를 알려면 메모리와 어드레스에 대한 이해가 필수인 거지요.

그래서 본격적으로 포인터에 대해 얘기하기 전에,

메모리와 연관지어서 기초적인 부분을 다시 정리해본 겁니다.

신고

'Application > C/C++' 카테고리의 다른 글

[강좌] 블럭쌓기 만들기 2일차  (4) 2011.06.05
[강좌] 블럭쌓기 만들기 1일차  (3) 2011.05.26
C 포인터 - 변수와 포인터  (0) 2011.03.21
포인터는 왜 어려울까?  (0) 2011.03.21
리눅스 채팅 클라이언트  (0) 2010.12.01
리눅스 채팅 서버  (0) 2010.12.01

Source :  http://minjang.egloos.com/2291148

 

 

왜 C/C++를 가장 강력하고 또 가장 어려운 언어라고 할까? 아마 대부분 이 물음에 ‘포인터’로 답할 것이다. 포인터는 강력함과 동시에 수 많은 어려움을 선사하여 많은 C/C++ 개발자를 괴롭힌다. 포인터로 고생하는 초보자들은 어디서나 볼 수 있다. 심지어는 포인터만 다룬 책들도 많이 있다. 도대체 포인터는 왜 이렇게 어려울까?

먼저, C/C++의 포인터 문법 자체가 복잡하다. 대부분 주소 값을 얻거나(&) 그 주소 값의 내용을 읽는 것(*)만 알아도 되지만 포인터 형태가 조금만 복잡해져도 사실 쉽지 않다. int *a[3]은 매우 간단하지만 int (*a)[3]만 되어도 그리 쉽게 머리 속에 그림이 잘 안 그려진다. 게다가 C++로 가면 클래스 멤버 함수까지 생기니 더 복잡해진다.

그런데 이건 어디까지나 문법의 문제다. 초보 개발자가 포인터형 자료구조나 함수 포인터에 쩔쩔매는 이유는 사실 문법이 어려워서가 아니다. 아무리 포인터를 공식에 맞춰 해석해도 데이터나 코드를 ‘가리킨다’라는 개념이 명확하지 않아서 그렇다.

포인터가 어려운 이유는 사실 매우 간단하다. ‘컴퓨터’를 몰라서 벌어지는 비극이다. 좀 더 정확히 쓰면 C/C++ 코드 한 줄이 어떻게 컴파일러가 번역하고, 어떻게 운영체제가 실행을 시키고, 마지막으로 어떻게 프로세서 내부에서 처리되어 메모리를 변화 시키는지 감이 없기 때문에 이해가 안가는 것이다. 컴퓨터 시스템의 기본 원리를 모르는데 야리꾸리한 비유를 동원해 포인터를 배우려 하니 더 헷갈릴 뿐이다.

여기서 대충 C 수업 숙제만 해결하면 되는 친구라면 컴퓨터 시스템 따위 공부해봤자 인생에 도움 안되니 대충 대충 넘어가도 된다. 그런데 최소한 이 바닥에서 진짜 개발자로 먹고 살려면 기본적인 컴퓨터 시스템에 대한 이해는 필수다. 그러면 포인터는 문제 되지 않는다. 이중포인터니 뭐 그런 소리를 할 필요도 없다. 포인터가 그냥 데이터나 코드를 가리킨다는 기본적인 사실에 왜 컴퓨터가 이런 표현을 필요로 하는지만 이해하면 끝난다.

간단한 문제를 하나 생각해보자.

a = a + 1;

위 코드에서 변수 a는 지역 변수이다. 그럴 때 이 코드가 어떻게 컴파일러에 의해 번역되어 어떻게 메모리를 변화시키는지 10분 이상 설명해보라.

. . .

이 질문에 막힘이 없는 친구라면 포인터로 절대 고생하지 않을 것이다. 그런 친구가 설사 포인터로 삽질한다 하더라도 그건 단순히 문법에 대한 혼동일 뿐이다. 이 질문에 답할 자신이 없다면 지금 C/C++ 책이나 무슨 디자인 패턴 책을 봐야 할 때가 아니다. 기본적인 컴퓨터 시스템부터 공부해야 한다.

위 문제를 이제 좀 더 자세히 살펴보자. 질문을 던졌던 코드를 x86 32비트로 컴파일하면 보통 아래처럼 번역된다.

mov  eax,dword ptr [ebp-4]
add  eax,1
mov  dword ptr [ebp-4],eax

아니면 바로 CISC 스타일로 표현되기도 한다.

inc  dword ptr [ebp-4]

여기서 내가 x86 기계어를 반드시 이해해야 한다고 말하는 것이 아니다. 내가 주장하는 것은 최소한 컴파일러가 어떻게 저 간단한 덧셈 문장을 기계어로 바꾸는지는 알아야 한다는 것이다. MIPS가 되었던 ARM이 되었던 상관없다. 살짝 형태만 다르지 기본 틀은 같다.

만약 위 기계어의 모든 부분을 하나도 빠짐 없이1 설명할 수 있다면 컴퓨터 시스템도 대부분 이해하고 있을 뿐만 아니라 포인터의 대부분도 이해한다는 뜻이다. 나머지는 함수 포인터에 대한 내용이긴 한데 역시 함수 호출이 스택에서 어떻게 이루어지는지만 알아도 문제가 되지 않는다.

이 기계어를 조금 설명하면, 변수 a의 값을 1을 증가시키려면 (1) 변수 a가 있는 주소의 내용을 임시 레지스터로 읽어오고, (2) 이 레지스터의 값을 하나 증가시키고, 마지막으로 (3) 변수 a가 있는 주소에 이 레지스터 내용을 써주는 것이다.

“a = a + 1”에는 어떠한 포인터 표현도 없다. 그런데 컴퓨터는 이걸 포인터로 해석해서 실행하는 것이다. 이렇게 포인터는 컴퓨터 기본 시스템 작동 원리만 알면 너무나 자연스러운 개념이 된다.

지금 저 무시하나효? 저 이 정도는 다 알아욤. 그래도 포인터는 어렵던데요?

라고 반문하시면 난 여전히 이 코드를 제대로 이해하지 못해서 벌어지는 일이라고 말하고 싶다. 정말 장담 하는데 저 간단한 덧셈 코드의 기계어 작동만 “다 알아도” 포인터는 진짜 아무것도 아니다. (추가: malloc/free, new/delete과 같은 힙 할당으로 인한 포인터 사용은 이 포스팅에서 다루는 내용이 아니다.) 

더 나가 왜 지역 변수 a가 ‘ebp-4’ 같은 주소에 있는지도 알면 매우 좋다. 이걸 알면 자동으로 스택과 함수 호출 규약도 자연스레 알 것이고, 왜 함수 호출 비용이 있고, 왜 컴파일러가 함수를 인라인하는지 등등 알게 되는 사실이 눈덩이처럼 불어난다.

그럼 나무라지만 말고 좀 친절히 책도 추천해주세요. 21일 완성 같은 거 없어요?

사실 난 21일 완성 시리즈를 참 좋아했다. 농담 아니고 나의 첫 번째 C 공부 역시 21일 완성으로 했다. 그런데 아쉽게도 지금까지 내가 열심히 떠든 “컴퓨터 시스템”에 대해 가볍게 볼 수 있는 책은 그리 많지 않다. 보통 대학교에서 강의하는 시스템 프로그래밍 정도 수업 내용을 참고하면 된다. 몇몇 대학교의 시스템 프로그래밍 강좌 홈페이지에가서 강의 자료 내려 받아 보는 것도 매우 좋다. 좀 더 내공을 더 기르고 싶으면 특정 CPU 아키텍처를 섭렵하면 된다. 예를 들어, x86의 내용을 알고 싶으면 여기에 가서 Volume 1과 Volume 3A를 참고 하면 된다. 다 보는 건 사실 말도 안되고 중요 챕터만 봐도 정말 많은 걸 알 수 있다.

 

두 줄 요약:

아놔. 요즘 컴퓨터 빠른데 이런 거 진짜 알아야 해요? STL 쓰는 법도 알아야 하고 디자인 패턴도...

네, 개발자, 적어도 C/C++ 개발자라면 꼭 아셔야 합니다.

1 대충 열거하면: opcode, 레지스터, 데이터 정렬 문제, CISC/RISC의 차이(더 이상 이 논쟁은 유효하지 않음), 캐시/메모리, 가상메모리, 스택/힙/코드 등등

p.s. 이번 달 마소에 “개발자 업그레이드 시나리오: 수퍼 개발자의 꿈”이라는 코너에 민망한 글을 하나 썼다. 블로그에 올리려니 넘 남사시러워 요즘 출판 업계도 불황이고 하니 직접 책을 사보시던가 아니면 가까운 서점에 나가셔서 보시기를 바란다. 그 기사에서 내가 주장한 바가 위에서 떠든 이야기랑 비슷하다. 수퍼 개발자가 되려면 기초 체력, 그러니까 기초 전산 실력이 매우 중요함을 역설했다. 서두에 살짝 포인터 이야기를 꺼냈는데 이 포스팅에서는 포인터를 가지고 물고 늘어진 것임.

신고

Source : http://blog.naver.com/muwoo850502/50032210312

 

   1: #include<stdio.h>
   2: #include<string.h>
   3: #include<sys/types.h>
   4: #include<sys/socket.h>
   5: #include<netinet/in.h>
   6: #include<arpa/inet.h>
   7: #include<unistd.h>
   8: #include<errno.h>
   9: #define PORT 7777
  10: #define BUFSIZE 1024
  11: void signalHandler(int signo);
  12: int sockfd;
  13: /*argv[1]은 수와 점 표기의 ip주소*/
  14: main(int argc,char 
  15: *argv[])
  16: {
  17: struct sockaddr_in servAddr;
  18: char 
  19: sendBuffer{BUFSIZE],recvBuffer[BUFSIZE];
  20: int recvLen;
  21: pid_t 
  22: pid;
  23: if(argc !=2)
  24: {
  25: fprintf(stderr,"Usage: %s 
  26: IP_address\n",argv[0]);
  27: exit(1);
  28: }
  29: /*소켓생성*/
  30: if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
  31: {
  32: perror("sock 
  33: failed");
  34: exit(1);
  35: }
  36: /*servAddr을 0으로 
  37: 초기화*/
  38: memset(&servAddr,0,sizeof(servAddr));
  39: /*servAddr에 주소정보 
  40: 저장*/
  41: servAddr.sin_family=AF_INET;
  42: servAddr.sin_addr.s_addr=inet_addr(argv[1]);
  43: servAddr.sin_port=htons(PORT);
  44: /*servAddr서버에 통신을 요청*/
  45: if(connect(sockfd,(struct 
  46: sockaddr*)&servAddr,sizeof(servAddr))==-1)
  47: {
  48: perror("connect 
  49: failed");
  50: exit(1);
  51: }
  52: /*자식프로세스 생성*/
  53: switch(pid=fork())
  54: {
  55: case 
  56: -1:
  57: perror("fork failed");
  58: exit(1);
  59: /*자식 프로세스는*/
  60: case 0:
  61: /*SIGINT시그널을 받으면 
  62: signalHandler를 실행하도록 
  63: 설정*/
  64: signal(SIGINT,signalhandler);
  65: /*SIGINT시그널을 받을 
  66: 때 까지 반복*/
  67: while(1)
  68: {
  69: /*sockfd 
  70: 소켓으로 들어오는 데이터를 받아 recvBuffer에 
  71: 저장*/
  72: if((recvLen=recv(sockfd,recvBuffer,BUFSIZE,0))==-1)
  73: {
  74: perror("recv 
  75: failed");
  76: exit(1);
  77: }
  78: recvBuffer[recvLen]='?';
  79: /*받은 데이터를 
  80: 출력*/
  81: printf("%s\n",recvBuffer);
  82: }
  83: break;
  84: /*부모 프로세스는*/
  85: default:
  86: /*quit를 입력받을 때까지 
  87: 반복*/
  88: while(1)
  89: {
  90: /*터미널로부터 데이터 
  91: 입력*/
  92: fgets(sendBuffer,BUFSIZE,stdin);
  93: if(!strncmp(sendBuffer,"quit",4))
  94: {
  95: /*자식프로세스에게 
  96: SIGINT시그널 
  97: 보냄*/
  98: kill(pid,SIGINT);
  99: break;
 100: }
 101: /*입력받은 데이터를 서버에게 
 102: 보냄*/
 103: if(send(sockfd,sendBuffer,strlen(sendBuffer),0)!=strlen(sendBuffer))
 104: {
 105: perror("send 
 106: failed");
 107: exit(1);
 108: }
 109: }
 110: }
 111: close(sockfd);
 112: exit(0);
 113: }
 114: /*SIGINT 시그널을 받으면 실행될 핸들러*/
 115: void signalHandler(int 
 116: signo)
 117: {
 118: close(sockfd);
 119: exit(0);
 120: }
신고

'Application > C/C++' 카테고리의 다른 글

C 포인터 - 변수와 포인터  (0) 2011.03.21
포인터는 왜 어려울까?  (0) 2011.03.21
리눅스 채팅 클라이언트  (0) 2010.12.01
리눅스 채팅 서버  (0) 2010.12.01
주변광 센서를 이용한 보다 스마트한 기기 구현하기  (0) 2010.11.02
D3DFORMAT  (0) 2010.11.02

Source : http://blog.naver.com/muwoo850502/50032210336

   1: #include<stdio.h>
   2: #include<string.h>
   3: #include<sys/types.h>
   4: #include<sys/socket.h>
   5: #include<netinet/in.h>
   6: #include<arpa/inet.h>
   7: #include<unistd.h>
   8: #include<errno.h>
   9:  
  10: #define PORT 7777
  11: #define MAXPENDING 5
  12: #define BUFSIZE 1024
  13:  
  14: main()
  15: {
  16:  int servSockfd;
  17:  int clntSockfd;
  18:  struct sockaddr_in servSockfd;
  19:  struct sockaddr_in clntSockfd;
  20:  char recvBuffer[BUFSIZE];
  21:  char sendBuffer[BUFSIZE];
  22:  int clntLen;
  23:  int recvLen;
  24:  
  25:  /*소켓 생성*/
  26:  if((servSockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
  27:  {
  28:   perror("sock failed");
  29:   exit(1);
  30:  }
  31:  /*servaddr를 0으로 초기화*/
  32:  memset(&servAddr,0,sizeof(servAddr));
  33:  /*servaddr에 주소 정보 저장*/
  34:  servAddr.sin_family=AF_INET;
  35:  servAddr.sin_addr.s_addr=htonl(INADDR_ANY);
  36:  servAddr.sin_port-htons(PORT);
  37:  
  38:  /*servsockfd 소켓에 주소정보 연결*/
  39:  if(bind(servSockfd,(struct sockaddr*)&servAddr,sizeof(servAddr))==-1)
  40:  {
  41:   perror("bind failed");
  42:   exit(1);
  43:  }
  44:  
  45:  /*servsockfd 소켓에 들어오는 클라이언트 요청 기다림*/
  46:  if(listen(servSockfd,MAXPENDING)==-1)
  47:  {
  48:   perror("listen failed");
  49:   exit(1);
  50:  }
  51:  
  52:  /*무한반복*/
  53:  while(1)
  54:  {
  55:   clntLen=sizeof(clntAddr);
  56:   /*servSockfd 소켓으로 들어오는 클라리언트 요청 받아들임*/
  57:   if((clntSockfd=accept(servSockfd,(struct sockaddr*)&clntAddr,&clntLen))==-1)
  58:   {
  59:    perror("accept failed");
  60:    exit(1);
  61:   }
  62:   printf("client is in\n");
  63:   /*자식프로세스 생성*/
  64:   switch(fork())
  65:   {
  66:   case -1:
  67:    perror("fork failed");
  68:    exit(1);
  69:  
  70:    /*자식프로세스는*/
  71:   case 0:
  72:    close(servSockfd);
  73:    /*임의의 클라이언트에 대해 반복*/
  74:    while(1)
  75:    {
  76:     /*clntSockfd 소켓으로 들어오는 데이터를 받아 recvBuffer에 저장*/
  77:     if((revcLen=recv(clntSockfd,recvBuffer,BUFSIZE,0))==-1)
  78:     {
  79:      perror("recv failed");
  80:      exit(1);
  81:     }
  82:     /*클라이언트가 연결을 끊으면 recv는 0을 반환*/
  83:     if(recvLen==0)
  84:      break;
  85:  
  86:     recvBuffer[recvLen]='?';
  87:     /*받은 데이터를 출력*/
  88:     printf("%s\n",recvBuffer);
  89:    }
  90:    close(clntSockfd);
  91:    exit(0);
  92:  
  93:    /*부모 프로세스는*/
  94:   default:
  95:    while(1)
  96:    {
  97:     /*터미널로부터 데이터 입력*/
  98:     fgets(sendBuffer,BUFSIZE,stdin);
  99:  
 100:     /*입력받은 데이터를 클라이언트에게 보냄*/
 101:     if(send(clntSockfd,sendBuffer,strlen(senBuffer),MSG_NOSIGNAL)!=strlen(sendBuffer))
 102:     {
 103:      /*상대방의 연결이 끊겨 호출에 실패하면 erroe에는 EPIPE가 저장*/
 104:      if(errno==EPIPE)
 105:      {
 106:       printf("client is out\n");
 107:       break;
 108:      }
 109:      perror("send failed");
 110:      exit(1);
 111:     }
 112:    }
 113:   }
 114:   close(clntSockfd);
 115:  }
 116: }
신고

'Application > C/C++' 카테고리의 다른 글

포인터는 왜 어려울까?  (0) 2011.03.21
리눅스 채팅 클라이언트  (0) 2010.12.01
리눅스 채팅 서버  (0) 2010.12.01
주변광 센서를 이용한 보다 스마트한 기기 구현하기  (0) 2010.11.02
D3DFORMAT  (0) 2010.11.02
[CPP] 디버깅에 관하여  (0) 2010.08.24

Source : http://www.ednkorea.com/print.asp?articleId=9537

 

ALS(Ambient-Light Sensor)는 오랫동안 업계에서 사용되어 왔지만 애플(Apple)의 아이폰 같은 스마트폰의 성공에 힘입어 인지도가 높아졌다. 아이폰은 주변 상황에 따라 디스플레이의 조명을 조정하여 전력 소모량을 줄이고 배터리 사용 시간을 늘리기 위해 ALS를 도입했다. 또한 ALS과 흡사한 근접 디텍터를 활용하여 사용자 행동 패턴에 따라 스스로 조명을 재설정하도록 하기도 했다. 이처럼 전력 소모량을 줄여야 하는 대형 LCD의 스마트폰이 현재 ALS의 주요 사용처이지만 앞으로의 양상은 다를 듯하다. 각종 애플리케이션들이 에너지 절약은 기본이고 향상된 사용자 편의성을 중요하게 여길 소지가 많기 때문이다. 예를 들면 대형 스크린 LCD TV는 주변 조명에 맞게 LED 백라이트가 조정돼야 하고, SSL 조명을 갖춘 방은 자연 조명 또는 입주자의 기분에 맞게 조명이 조정될 수 있기 때문이다. 더불어 자동차 조명은 주간 또는 야간 주행 또는 도로의 밝기 여부에 따른 반사를 수용할 수 있어 전력 소모를 줄이고 좀 더 나은 사용자 경험을 제공할 수도 있다.

clip_image001
ALS는 포토다이오드와 포토트랜지스터로 구성된다. 그러나 단순한 광 감지 반도체로는 불충분하다. 그것은 ALS가 ‘포토옵틱(Photoptic)’이어야 하기 때문이다. 이것은 다시 말해 인간의 눈(그림 1)과 동일한 주파수 스펙트럼을 감지해야 한다는 것을 의미한다. 백열등과 HID(High-Intensity-Discharge) 등은 열 발산으로 인해 눈에 보이지 않는 IR(Infrared) 대역에서 복사 에너지의 50%~60%를 소모한다. 인터실(Intersil)에서 ALS 제품을 담당하는 오레게 스테치베(Oleg Steciw) 마케팅 매니저에 의하면, HID는 가장 좋은 스펙트럼 응답 성능을 지닌 제품을 사용해야 한다. 그 이유에 대해 그는 “그렇지 않을 경우, 누군가가 방에 있다고 가정을 해보자. 그 때 백라이트는 갑자기 미친 듯이 동작하게 될 것인데, 그렇게 되면 그의 눈에 보이지 않는 어떤 외부 광원이 혼란을 불러 일으키기 때문이다.”라고 설명했다.

이 같은 상황을 방지하기 위한 차원으로 애로우 일렉트로닉스(Arrow Electronics)의 조명팀에 근무하는 베르너 마쉬그(Werner Mashig) 애플리케이션 엔지니어에 따르면, 어떤 제조사들은 센서가 인간의 눈처럼 응답하도록 적외선을 걸러내기 위해 에폭시에 IR 필터를 부착하기도 한다. ALS에 다수의 포토다이오드를 사용하는 것도 해결 방법이다. TAOS(Texas Advanced Optoelectronic Solutions)의 카를로 스트립폴리(Carlo Strippoli) 마케팅 및 세일즈 부회장은 “두 개의 포토다이오드를 사용할 경우, 첫 번째 포토다이오드는 300에서 1100nm까지 모든 것을 보는 광대역 제품이 될 것이고, 두 번째 다이오드는 전용 IR 포토다이오드로 센서에 도달하는 IR을 감시하여 광대역 포토다이오드에서 수신된 IR을 제거하는 역할을 수행할 것”이라고 말했다.

ADC의 필요성

형광등은 백열등 또는 HID등 보다 좀 더 효율적이어서 IR 범위에서 복사 에너지를 거의 방출하지 않지만, 의도되지 않는 ALS 트리거링을 야기하는 60Hz 플릭커 현상을 발생시키기도 한다. 그러나 최신의 디지털 ALS는 ADC를 내장하고 있어 디지털 통신 버스와 통신하기 위해 광전류를 디지털 신호로 변환한다. 이 경우 ADC는 고해상도 샘플링을 통해 60Hz 플릭커 같은 광학 잡음을 제거하므로 두 가지 역할을 수행하는 것이다. 이와 관련된 업계 동향에서 로옴(Rohm)의 BH17xx 시리즈는 0lux~65,000lux 영역에 걸쳐 1lux 해상도를 제공하는 16bit ADC가 포함돼 있어 주목할 필요가 있다. 고해상도 샘플링 모드에서 ADC는 광학 잡음을 걸러 내지만 GPS(Global Positioning System) 같은 애플리케이션에 적절한 좀 더 짧은 샘플링 시간을 사용하는 저해상도 모드에서 빛의 세기는 동적으로 변한다. 특히 A-GPS 시스템은 자동차 실내 또는 자연 광 환경에서 동작하기 때문에 이상적인 ALS는 광원에 상관없이 동일한 민감도를 보여준다.

TAOS의 스트립폴리는 “ALS가 진화해야 할 방향은 디지털이다. 이는 I²C(Inter Integrated Circuit) 같은 싱글 2선 버스에 다수의 센서를 연결시킬 수 있도록 하기 때문이다.”라고 설명했다. 스트립폴리가 설명한 이러한 특징은 폴더형 휴대폰에 특히 중요하다. 디지털 버스는 휴대폰의 폴더가 열리는 경계면에 필요한 선의 수를 최소화시킨다. 업계에 의하면 아날로그 인터페이스는 모든 센서에 최소한 2개의 선을 필요로 한다. 따라서 아날로그 ALS는 ALS의 전압 또는 전류 출력이 조명 서브 시스템을 구동시키는 특정한 설계일 경우 여전히 잘 어울린다. 이러한 서브 시스템은 마이크로컨트롤러 또는 가용한 ADC 입력이 부족한 것은 사실이지만 가격이 중요한 요소인 저가의 설계에서는 유용하다.(그림 2)

예전의 경우 ALS는 총 전류에 따른 부품에 의해 달라질 수 있었다. 이러한 변이는 엄격한 민감도 범위를 위한 설계를 어렵게 만드는 요인이었다. 그러나 지금은 상황이 달라졌다. 애로우의 마쉬그는 “이제 제조사들은 설계에 좀 더 일관성을 주어 광전류의 변이가 많지 않도록 하는 부품의 비닝(Binning)을 잘 수행하고 있다.”고 밝혔다. 제조사들의 비닝의 엄격함을 확인하기 위해 광전류에 따른 밝기를 유심히 살펴볼 것을 권고하고 있다.

저전력 조명은 배터리로 동작하는 기기에 특히 중요하며, 그에 따른 필요치는 ALS에 이미 포함되어 있다. 일반적으로 ALS 아날로그 및 디지털 제품은 모두 셧다운과 슬립모드를 가지고 있어 약 1?A에서 센서가 동작한다. 아날로그 ALS는 상대적으로 단순하기 때문에 디지털에 비해 전류를 적게 필요로 한다. 예를 들면 대표적인 디지털 ALS는 ADC 통합에 의해 액티브 모드에서 190?A를, 전원 차단 모드에서는 1?A를 소모하지만 동등한 아날로그 부품은 각각 97?A와 0.4?A밖에 소모하지 않는다. 그러나 별도의 ADC를 갖춘 아날로그 ALS와 비교하면 전체 전력 소모는 유사하거나 약간 적다.

근접 디텍터의 역할

스마트폰은 ALS 외에도 근접 디텍터를 종종 사용하기도 한다. 애플이 행한 아이폰에서의 근접 디텍터 통합은 휴대형 컨수머 기기가 사용자와 상호작용할 때 좀 더 지능적으로 동작하도록 촉구한다.(박스기사 ‘근접 디텍터를 도입한 아이폰’ 참조) ALS와 근접 디텍터는 기술 및 사용법이 유사하기 때문에 ALS 업체들은 ALS의 통합 기능 목록에 근접 디텍터를 포함시키고 있다. 인터실의 스테치베는 “우리가 출시한 ISL29011은 외부 IR LED를 구동하여 LED의 투과성을 동기화시킨 후 정면에서 사물의 반사를 포착한다. 그것은 사용자들이 3cm~5cm 정도에서 감지를 원하기 때문이다.”라고 밝혔다.

센서 패키지 외부에 위치한 IR LED는 디바이스를 부착시키는 위치 또는 기기 후면에 어떤 것을 부착시킬지에 대해 좀 더 유연성을 가지도록 해준다. TAOS의 스트립폴리는 “아이폰은 95%의 가시광선을 차단하는 유리 뒤에 근접 디텍터를 부착했기 때문에 만일 고정형 싱글 출력을 제공하는 디바이스를 사용한다면 매우 낮은 신호를 얻게 된다.”고 설명했다.

디스크리트 근접 센서에서 센서 패키지 내부에 IR 발산 LED를 포함하는 것은 여전히 일반적이다. 최근 아바고(Avago)는 내장 신호 조절 IC, 에미터, 디텍터를 하나의 패키지에 포함하고 아날로그 및 디지털 입력을 모두 옵션으로 제공하는 APDS-9120 근접 센서를 선보였다. 스테치베처럼 스트립폴리도 휴대형 기기의 전력 절감 필요치가 ALS에 근접 디텍터를 패키지화하는 추세를 이끌고 있다고 본다. 그러나 그는 좀 더 친환경 제품을 위한 움직임의 일부로 그 추세를 판단한다는 것은 약간 다른 견해이다. 스트립폴리는 특히 아시아 국가들은 근접 모니터링을 통해 사용자가 대형 스크린 또는 모니터를 보고 있는지 분별할 수 있는 기능을 요구할 것으로 판단하고 있다.

스마트폰의 ALS는 빛의 세기를 검출하지만 컬러 스펙트럼에 대한 정보까지 제공하지는 않는다. ALS의 최근 개발 동향을 보면 대형 스크린 LCD에 필요한 RGB(Red/Green/Blue) 검출 기능이 포함되고 있다. 최고의 경험을 제공하기 위해 이러한 디스플레이들은 주변 조명의 온도 색깔에 백라이팅을 일치시켜야 한다.(참고자료 1) 따라서 LCD 컨트롤러는 RGB ALS 출력을 통해 RGB HB(High Brightness) LED를 조정하여 실내 조명에 맞춘다. 그래서 형광등을 사용하는 방의 백라이팅은 자연 또는 백열등을 사용하는 방과는 다른 색깔 온도를 가지게 된다. 추가적으로 RGB LED가 오래될수록 색깔은 약간 변하게 되므로, 백라이트 자체에 추가적인 RGB ALS를 사용하면 LED 색깔 변경에 따른 피드백을 제공할 수 있다. 인터실, TAOS, 로옴은 모두 관련된 RGB 센서를 제공하고 있다.

SSL은 RGB ALS용으로 떠오르는 애플리케이션이다. 이러한 애플리케이션에서 컬러 센서는 방의 조명 제어 시스템에 HB LED 기반의 조명 기구의 세기, 색깔, 출력 온도를 조정하기 위한 피드백을 준다. 조명 제어는 실내 조명이 현재 사용하는 켜고 끄는 단순한 스위치 정보 보다 좀 더 복잡해야 하는 것이 당연하기 때문에 이를 실현하려면 조명 설계자들이 통신 프로토콜들과 친숙해야 한다. 극장 조명에 수년간 사용되고 있는 DALI(Digital Addressable Lighting Interface) 프로토콜은 유사한 접근법으로 볼 수 있다.(박스기사 ‘DALI 활용한 MCU로 조명센서 설계’ 참조)

자동차 조명 또한 ALS를 필요로 한다. 수년간 야간 주행 애플리케이션은 조명을 켜고 끄기 위해 단순한 포토센서를 사용하고 있지만 ALS는 컬러 조명과 조명의 세기 변이 같이 안전 운행과 미학을 위해 실내 조명을 최적화시킬 수 있다. 따라서 대부분의 다른 자동차 부품처럼 ALS 사양에도 좀 더 넓은 범위의 온도 및 진동 범위가 포함되어야 한다.

요약

? ALS(Ambient-Light Sensor)의 주요 사용처가 현재 스마트폰 등 일부에 국한되어 있지만 노트북, TV 스크린, 자동차, 실내 조명 같은 애플리케이션에 활용되면 지능형 기기를 구현할 수 있으면서도 전력 절감을 실현할 수 있다.

? ALS의 가장 중요한 특징은 인간의 눈처럼 빛을 감지할 수 있다는 것이다. 이를 위해서는 적외선 스펙트럼을 필터로 걸러내야 한다.

? 제조사들은 ALS에 디지털 인터페이스, 근접 센서를 포함하는 좀 더 많은 기능을 통합시키고 있다.

? 좀 더 우수한 디바이스들은 RGB(Red/Green/Blue)를 감지할 수 있다.

웹사이트

Apple www.apple.com

Arrow Electronics www.arrow.com

Avago Technologies www.avagotech.com Intersil www.intersil.com

Microsemi www.microsemi.com

NEC Electronics www.necel.c Optek www.optek.com

Osram www.osram.com

Panasonic pewa.panasonic.com Rohm www.rohmsemiconductor.com

Sharp www.sharpmeg.com

TAOS www.taosinc.com Toshiba www.toshiba.com

Vishay www.vishay.com

저자

마게리 코너(Margery Conner) 기자의 연락처는 전화 1-805-461-8242, 이메일 mconner@connerbase.com이다.

참고자료

1. Conner, Margery, “The direction of light: Electronic and thermal improvements bring advances to lighting technologies,” EDN, Feb 5, 2009, pg 26.

이미지를 보시려면 여기를 클릭하세요:

그림 1, 그림 2

Main pic:

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

3G(Third Generation) 아이폰의 근접 센서는 적색 원으로 표시되어 있고, ALS는 그 좌측의 녹색 부분이다. 아이폰의 스피커는 흑색의 그물형 타원이다.(자료제공: iFixit) 조명 및 근접 센서는 종종 휴대폰 스피커 옆에 위치하는데, 센서와 스피커가 외부와의 접속에 필요하기 때문이다. 마이크로폰 주변의 습기를 감안한다면 마이크로폰보다는 스피커가 좀 더 나은 선택이다.

Figure 1

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

그림 1. 인간의 눈은 약 380nm~780nm까지의 파장에 민감하며, 가장 민감한 파장은 555nm이다. 좀 더 넓은 적색 곡선은 대표적인 ALS의 민감도를 보여준다.

Figure 2

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

그림 2. 디지털 ALS가 존재하지만 아날로그 센서는 여전히 많은 애플리케이션에서 활용되고 있다. 마이크로세미(Microsemi)의 Best Eye 프로세싱은 거의 완벽에 가까운 포토옵틱 광 파장 응답 곡선을 제공한다. 이 센서의 출력은 넓은 다이내믹 레인지의 압축 증폭기에 입력되어 50개가 넘는 실내 조명에서 정밀한 해상도를 보장한다.

근접 디텍터를 도입한 아이폰

애플의 아이폰은 매끈한 디자인에 ALS(Ambient Light Sensor), 가속도계, 근접 센서 같은 여러 개의 센서를 도입한 것이 특징이다. 그러나 디스플레이가 터치 센서를 지원하RL 때문에 휴대폰을 얼굴에 대고 사용할 때는 의도하지 않은 문제가 발생할 수 있다. 애플은 근접 센서를 도입하여 의도하지 않은 스크린 동작 문제를 해결했다. 이 센서가 근접성을 감지하여 휴대폰이 사용자 얼굴에서부터 3cm~5cm로 접근하면 터치 기능을 차단시키기 때문이다.

참고자료

? “iPhone 3G Teardown.”

DALI 활용한 MCU로 조명센서 설계

글/ 바비 웡(Bobby Wong), NEC 일렉트로닉스 아메리카

에너지 소모를 줄이는 단순한 방법 중 하나는 자연광을 활용하여 사무실 조명을 조절하는 것이다. 다수의 위치에서 동작하는 광 센서들은 자연적으로 발생하는 실내 빛의 양을 검출한다. 적절한 조명 시스템을 통해 사용자는 각 영역에 필요한 전체 빛의 양을 생성할 수 있도록 사무실 조명을 조정할 수 있는 것이다. 실내 조명을 감지하여 에너지 효율성을 향상시키는 것부터 출력 조명의 검출을 통해 컬러를 향상시키는 것까지 센서는 조명 시스템을 극적으로 향상시킬 수 있다. 센서가 조명에 데이터를 제공하는 것은 사실이지만, 그 데이터를 수신하고 처리하는 것은 조명 시스템이기 때문에 거기에는 지능적인 마이크로컨트롤러를 필요로 한다.

에너지를 절약하는 것도 중요하지만 더 중요한 것은 에너지 절약이 생산성을 줄여서는 안 된다는 것이다. 똑똑한 마이크로컨트롤러 기반의 조명 시스템은 필요할 경우 사용자가 자동으로 조절되는 조명 레벨 센서를 무시할 수 있도록 하며, 사용자 경험을 향상시키기 위해 프로그램된 사용자 설정을 기억하도록 한다.

비록 여러 지역의 조명 제어, 센서 입력/프로세싱, 장면 설정은 복잡하게 들리겠지만 사무실과 공장의 백색 광 제어를 위한 DALI(Digital Addressable Lighting Interface) 프로토콜은 이 기능을 이미 구현하고 있다. 회사들은 이러한 센서를 설치하여 여러 시설에 걸쳐 조명을 운용하고 있기 때문에 네트워크가 필요하다. DALI 네트워크는 슬라이더 딤머 센서 같은 64개의 일반적인 제어를 통해 64개에 달하는 조명을 컨트롤할 수 있다. 각 영역의 조명은 16개의 장면까지 저장할 수 있으며, 각 장면은 0에서 255의 디지털 디밍 레벨을 가지고 있다.

센서가 마이크로컨트롤러로 실내 조명을 입력할 때, 마이크로컨트롤러는 네트워크를 통해 64개의 조명 중 어떤 것에라도 DALI 명령을 전달하여 특정하게 디밍을 할 수 있도록 한다. 또한 DALI 프로토콜은 확장성을 지녀 고유의 기능을 추가할 수도 있다. 몇몇 마이크로컨트롤러는 형광 튜브부터 LED까지 구동할 수 있는 특수 하드웨어를 보유하여 DALI 네트워크 지원을 용이하게 만든다. 디스크리트 광 드라이버와 달리 이러한 마이크로컨트롤러는 DALI 프로토콜을 사용하여 센서 입력을 처리하고 넓은 공간의 조명을 지능적으로 제어할 수 있어 도처에서 빛의 양을 최적화하고 에너지를 절감시킨다.

저자

바비 웡(Bobby Wong)은 NEC 일렉트로닉스 아메리카(NEC Electronics America)의 마이크로컨트롤러 전략 사업 유닛의 기술 마케팅 엔지니어이다.

참고자료

? “Lighting-control solutions,” NEC Electronics America.

신고

다양한 종류의 표면 포맷을 정의한다.

구문

typedef enum _D3DFORMAT {

...(values)

} D3DFORMAT;

포맷에는 몇개의 종류가 있다.

모든 포맷은, 왼쪽에서 오른쪽으로 최상정도 비트 (MSB)로부터 최하정도 비트 (LSB)의 순서에 나타나고 있다. 예를 들어, D3DFORMAT_ARGB 는, MSB 채널 A (알파)로부터 LSB 채널 B (파랑)의 순서이다. 표면 데이터를 암벽 횡단 할 때 데이터는 LSB 로부터 MSB 의 순서로 메모리에 저장 된다. 이것은, 메모리내의 채널의 순서가, LSB (파랑)로부터 MSB (알파)의 순서인 것을 의미한다.

미정도리의 채널 (G16R16 나 A8 등)을 포함한 포맷의 디폴트값은 1 이다. 유일한 예외는 A8 포맷으로, 3 개의 컬러 채널에 대해서 000 에 초기화된다.

부호 없음 포맷

이러한 정수는, 픽셀 셰이더에 대한 텍스처 주소 명령의 작동코드를 참조한다.

부호 없음 포맷의 데이터는, 정이 아니면 안된다. 부호 없음 포맷에서는, 적 (R), 록 (G), 청 (B), 알파 (A), 휘도(Luminance) (L), 팔레트 (P) 데이터를 조합해 사용한다. 팔레트 데이터는, 색팔레트의 인덱스 생성에 사용하므로, 컬러 인덱스 데이터라고도 부른다.

부호 없음 포맷의 플래그 포맷
D3DFMT_R8G8B8 20 24 비트의 RGB 픽셀 포맷으로, 채널 근처 8 비트를 사용한다.
D3DFMT_A8R8G8B8 21 32 비트의 알파 첨부 ARGB 픽셀 포맷으로, 채널 근처 8 비트를 사용한다.
D3DFMT_X8R8G8B8 22 32 비트의 RGB 픽셀 포맷으로, 각 색에 8 비트가 확보되고 있다.
D3DFMT_R5G6B5 23 16 비트의 RGB 픽셀 포맷으로, 빨강에 5 비트, 초록에 6 비트, 파랑에 5 비트를 사용한다.
D3DFMT_X1R5G5B5 24 16 비트의 픽셀 포맷으로, 그 중 5 비트는 각 색을 위해서(때문에) 확보되고 있다.
D3DFMT_A1R5G5B5 25 16 비트의 픽셀 포맷으로, 각 색에 5 비트, 알파에 1 비트가 확보되고 있다.
D3DFMT_A4R4G4B4 26 16 비트의 ARGB 픽셀 포맷으로, 채널 마다 4 비트를 사용한다.
D3DFMT_R3G3B2 27 8 비트의 RGB 텍스처 포맷으로, 빨강에 3 비트, 초록에 3 비트, 파랑에 2 비트를 사용한다.
D3DFMT_A8 28 8 비트의 알파만.
D3DFMT_A8R3G3B2 29 16 비트의 ARGB 텍스처 포맷으로, 알파에 8 비트, 빨강과 초록에 각각 3 비트, 파랑에 2 비트를 사용한다.
D3DFMT_X4R4G4B4 30 16 비트의 RGB 픽셀 포맷으로, 색 마다 4 비트를 사용한다.
D3DFMT_A2B10G10R10 31 32 비트의 픽셀 포맷으로, 각 색에 10 비트, 알파에 2 비트를 사용한다.
D3DFMT_A8B8G8R8 32 32 비트의 알파 첨부 ARGB 픽셀 포맷으로, 채널 근처 8 비트를 사용한다.
D3DFMT_X8B8G8R8 33 32 비트의 RGB 픽셀 포맷으로, 각 색에 8 비트가 확보되고 있다.
D3DFMT_G16R16 34 32 비트의 픽셀 포맷으로, 초록과 빨강에 각각 16 비트를 사용한다.
D3DFMT_A2R10G10B10 35 32 비트의 픽셀 포맷으로, 적·록·청에 각각 10 비트, 알파에 2 비트를 사용한다.
D3DFMT_A16B16G16R16 36 64 비트의 픽셀 포맷으로, 성분 마다 16 비트를 사용한다.
D3DFMT_A8P8 40 8 비트의 알파가 붙은 8 비트의 컬러 인덱스 데이터.
D3DFMT_P8 41 8 비트의 컬러 인덱스 데이터.
D3DFMT_L8 50 8 비트의 휘도(Luminance)만.
D3DFMT_L16 81 16 비트의 휘도(Luminance)만.
D3DFMT_A8L8 51 16 비트로, 알파와 휘도(Luminance)에 각각 8 비트를 사용한다.
D3DFMT_A4L4 52 8 비트로, 알파와 휘도(Luminance)에 각각 4 비트를 사용한다.

부호 첨부 포맷

부호 첨부 포맷의 데이터는, 정이어도 부여도 괜찮다. 부호 첨부 포맷에서는, (U), (V), (W), (Q) 데이터를 조합해 사용한다.

부호 첨부 포맷의 플래그 포맷
D3DFMT_V8U8 60 16 비트의 범프 맵 포맷으로, u 데이터와 v 데이터에 각각 8 비트를 사용한다.
D3DFMT_Q8W8V8U8 63 32 비트의 범프 맵 포맷으로, 채널 마다 8 비트를 사용한다.
D3DFMT_V16U16 64 32 비트의 범프 맵 포맷으로, 채널 마다 16 비트를 사용한다.
D3DFMT_Q16W16V16U16 110 64 비트의 범프 맵 포맷으로, 성분 마다 16 비트를 사용한다.
D3DFMT_CxV8U8 117 16 비트의 보통 압축 포맷. 텍스처 샘플러는 다음과 같이 C 채널을 계산한다. C = sqrt(1 - U2 - V2)

믹스 포맷

믹스 포맷에는, 부호 없음 데이터와 부호 첨부 데이터를 조합해 저장 할 수 있다.

믹스 포맷의 플래그 포맷
D3DFMT_L6V5U5 61 휘도(Luminance) 첨부의 16 비트 범프 맵 포맷으로, 휘도(Luminance)에 6 비트, v 와 u 에 각각 5 비트를 사용한다.
D3DFMT_X8L8V8U8 62 휘도(Luminance) 첨부의 32 비트 범프 맵 포맷으로, 채널 마다 8 비트를 사용한다.
D3DFMT_A2W10V10U10 67 32 비트의 범프 맵 포맷으로, 알파에 2 비트, w, v, u 에 각각 10 비트를 사용한다.

FOURCC 포맷

4 문자 코드 (FOURCC) 포맷의 데이터는, 압축 데이터이다.

MAKEFOURCC

4 문자 코드를 생성하는 매크로를 다음에 나타낸다.

#define MAKEFOURCC(ch0, ch1, ch2, ch3)                              \
                ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) |   \
                ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 ))

정의 끝난 FOURCC 포맷을 다음에 나타낸다.

FOURCC 플래그 포맷
D3DFMT_MULTI2_ARGB8 MAKEFOURCC('M', 'E', 'T', '1') MultiElement 텍스처 (압축 없음)
D3DFMT_G8R8_G8B8 MAKEFOURCC('G', 'R', 'G', 'B') YUY2 (Y0U0, Y1V0, Y2U2 등)에 유사한 16 비트에 팩 된 RGB 포맷. 색값을 올바르게 나타내기 위해서(때문에), 픽셀의 페어를 필요로 한다. 페어의 1 번째의 픽셀은, 초록의 8 비트 (상위 8 비트)와 빨강의 8 비트 (하위 8 비트)를 포함한다. 2 번째의 픽셀은, 초록의 8 비트 (상위 8 비트)와 파랑의 8 비트 (하위 8 비트)를 포함한다. 2 개의 픽셀은, 함께 빨강과 파랑의 성분을 공유하고 있지만, 동시에 각각이 고유의 초록 성분 (G0R0, G1B0, G2R2 등)을 갖는다. 텍스처 샘플러는, 픽셀 셰이더내를 참조할 경우에 색을 정규화하지 않는다. 색은 0.0f ~ 255.0f 의 범위대로 된다. 이것은 모든 프로그래밍 가능한 픽셀 셰이더 모델에 들어맞는다. 고정 기능 픽셀 셰이더에 경우는, 하드웨어로 0. f ~ 1. f 의 범위에 정규화할 필요가 있어, 본질적으로 YUY2 텍스처로서 처리할 필요가 있다. 이 포맷을 공개하는 하드웨어는,D3DCAPS9 의 PixelShader1xMaxValue 멤버가, 그 범위를 처리할 수 있는 값으로 설정되지 않으면 안 된다.
D3DFMT_R8G8_B8G8 MAKEFOURCC('R', 'G', 'B', 'G') UYVY (U0Y0, V0Y1, U2Y2 등)에 유사한 16 비트에 팩 된 RGB 포맷. 색값을 올바르게 나타내기 위해서(때문에), 픽셀의 페어를 필요로 한다. 페어의 1 번째의 픽셀은, 초록의 8 비트 (하위 8 비트)와 빨강의 8 비트 (상위 8 비트)를 포함한다. 2 번째의 픽셀은, 초록의 8 비트 (하위 8 비트)와 파랑의 8 비트 (상위 8 비트)를 포함한다. 2 개의 픽셀은, 함께 빨강과 파랑의 성분을 공유하고 있지만, 동시에 각각이 고유의 초록 성분 (R0G0, B0G1, R2G2 등)을 갖는다. 텍스처 샘플러는, 픽셀 셰이더내를 참조할 경우에 색을 정규화하지 않는다. 색은 0.0f ~ 255.0f 의 범위대로 된다. 이것은 모든 프로그래밍 가능한 픽셀 셰이더 모델에 들어맞는다. 고정 기능 픽셀 셰이더에 경우는, 하드웨어로 0. f ~ 1. f 의 범위에 정규화할 필요가 있어, 본질적으로 YUY2 텍스처로서 처리할 필요가 있다. 이 포맷을 공개하는 하드웨어는,D3DCAPS9 의 PixelShader1xMaxValue 멤버가, 그 범위를 처리할 수 있는 값으로 설정되지 않으면 안 된다.
D3DFMT_DXT1 MAKEFOURCC('D', 'X', 'T', '1') DXT1 압축 텍스처 포맷
D3DFMT_DXT2 MAKEFOURCC('D', 'X', 'T', '2') DXT2 압축 텍스처 포맷
D3DFMT_DXT3 MAKEFOURCC('D', 'X', 'T', '3') DXT3 압축 텍스처 포맷
D3DFMT_DXT4 MAKEFOURCC('D', 'X', 'T', '4') DXT4 압축 텍스처 포맷
D3DFMT_DXT5 MAKEFOURCC('D', 'X', 'T', '5') DXT5 압축 텍스처 포맷
D3DFMT_UYVY MAKEFOURCC('U', 'Y', 'V', 'Y') UYVY 포맷 (PC98 준거)
D3DFMT_YUY2 MAKEFOURCC('Y', 'U', 'Y', '2') YUY2 포맷 (PC98 준거)

버퍼 포맷

깊이 버퍼, 스텐실 버퍼, 정점 버퍼, 인덱스 버퍼는, 각각 고유의 포맷을 갖는다.

버퍼 플래그 포맷
D3DFMT_D16_LOCKABLE 70 16 비트의 Z 버퍼 비트 깊이.
D3DFMT_D32 71 32 비트의 Z 버퍼 비트 깊이.
D3DFMT_D15S1 73 16 비트의 Z 버퍼 비트 깊이로, 15 비트가 깊이 채널에, 1 비트가 스텐실 채널에 확보되고 있다.
D3DFMT_D24S8 75 32 비트의 Z 버퍼 비트 깊이로, 깊이 채널에 24 비트, 스텐실 채널에 8 비트를 사용한다.
D3DFMT_D24X8 77 32 비트의 Z 버퍼 비트 깊이로, 깊이 채널에 24 비트를 사용한다.
D3DFMT_D24X4S4 79 32 비트의 Z 버퍼 비트 깊이로, 깊이 채널에 24 비트, 스텐실 채널에 4 비트를 사용한다.
D3DFMT_D32F_LOCKABLE 82 깊이값을 표준 IEEE 부동 소수점수(실수)값으로 나타내는 잠금 가능한 포맷.
D3DFMT_D24FS8 83 24 비트의 깊이 (24 비트 부동 소수점 포맷 - 20e4)와 8 비트의 스텐실을 포함한, 잠글 수 없는 포맷.
D3DFMT_D16 80 16 비트의 Z 버퍼 비트 깊이.
D3DFMT_VERTEXDATA 100 정점 버퍼 표면을 기술한다.
D3DFMT_INDEX16 101 16 비트의 인덱스 버퍼의 비트 깊이.
D3DFMT_INDEX32 102 32 비트의 인덱스 버퍼의 비트 깊이.

D3DFMT_D16_LOCKABLE 를 제외하는 모든 스텐실 포맷은, 각 픽셀에 특정의 비트 오더를 지정하지 않기 때문에, 드라이버는 깊이 채널로서 지정된 비트수보다 넓은 채널을 사용할 수 있다 (다만, 스텐실 채널은 사용할 수 없다).

부동 소수점 포맷

이러한 플래그는, 부동 소수점의 표면 포맷에 사용한다. 채널 근처 16 비트를 사용하는 이러한 포맷은, s10e5 포맷이라고도 부른다.

부동 소수점의 플래그 포맷
D3DFMT_R16F 111 16 비트의 부동 소수점 포맷으로, 빨강의 채널에 16 비트를 사용한다.
D3DFMT_G16R16F 112 32 비트의 부동 소수점 포맷으로, 빨강의 채널에 16 비트, 초록의 채널에 16 비트를 사용한다.
D3DFMT_A16B16G16R16F 113 64 비트의 부동 소수점 포맷으로, 알파·청·록·적의 채널 마다 16 비트를 사용한다.

IEEE 포맷

이러한 플래그는, 부동 소수점의 표면 포맷에 사용한다. 채널 근처 32 비트를 사용하는 이러한 포맷은, s23e8 포맷이라고도 부른다.

부동 소수점의 플래그 포맷
D3DFMT_R32F 114 32 비트의 부동 소수점 포맷으로, 빨강의 채널에 32 비트를 사용한다.
D3DFMT_G32R32F 115 64 비트의 부동 소수점 포맷으로, 빨강의 채널에 32 비트, 초록의 채널에 32 비트를 사용한다.
D3DFMT_A32B32G32R32F 116 128 비트의 부동 소수점 포맷으로, 알파·청·록·적의 채널 마다 32 비트를 사용한다.

그 외

그 외의 플래그는, 이것뿐이어, 미정도리의 포맷에 사용한다.

그 외의 플래그 포맷
D3DFMT_UNKNOWN 0 표면 포맷은 불명하다.

백 버퍼 또는 디스플레이 포맷

이러한 포맷은, 백 버퍼 또는 디스플레이 에 대해서만 유효하다.

포맷 백 버퍼. 디스플레이
A2R10G10B10 x x (풀 스크린 모드만)
A8R8G8B8 x  
X8R8G8B8 x x
A1R5G5B5 x  
X1R5G5B5 x x
R5G6B5 x x

주의

비트 오더는, 최상정도 바이트가 선두이다. 따라서, D3DFMT_A8L8 는, 이 2 바이트 포맷의 상위 바이트가 알파인 것을 나타내고 있다. D3DFMT_D16 는, 16 비트의 정수값으로, 애플리케이션으로 잠금 가능한 표면을 나타낸다.

픽셀 포맷이 선택되고 있는 것은, 확립되어 있는 FOURCC 방식을 도입할 뿐만 아니라, 하드웨어 벤더가 정의하는 확장 포맷의 표현을 가능하게 하기 위한(해)이다. Microsoft? Direct3D? 런타임이 인식하는 포맷군은,D3DFORMAT 로 정의되고 있다.

독립한 하드웨어 vender (IHV)가 제공하는 포맷 및 많은 FOURCC 코드는, 일람에는 나타나지 않기 때문에 주의할 필요가 있다. 이 열거형의 포맷은, 런타임에 의해 인정되고 있는 점이 다른 포맷과 다르다. 즉, 레퍼런스 래스터라이저는, 이러한 형태의 모두로 동작한다. IHV 제공의 포맷은, 카드 마다 각각의 IHV 가 지원 한다.

신고

+ Recent posts