Sandisk Cruzer micro 8GB 로 부팅을 해보자.

Posted by Programmer™
2013. 1. 7. 16:13 카테고리 없음

최근 들어 USB 의 가격이 많이 저렴해져서 누구나 하나씩은 들고다니는 생활 필수품이 되었다. Sandisk Extreme Z80 USB 3.0  32GB 의 경우도 2013년 1월 7일 현재 37,000 원 정도면 구입가능하다.

필자의 경우 478 Slot Type 의 2005년도에 조립한 구형 컴퓨터가 있는데, 아직까지는 인터넷 서핑용으로 그럭 저럭 쓸만하다.

그런데 슬림형 타입의 케이스이다 보니 DVD-ROM 을 세로로 세워서 설치하게끔 되어있다. 세로로 설치하는 경우의 문제는 오랜 시간이 지나다 보면 안의 CD 가 배출이 되지 않고 헛도는 현상이 일어나게 된다는 점이다. 이런 경우 XP 를 한번 설치할려면 정말 짜증아닌 짜증이 밀려오게 마련이다. 그래서 USB 로 XP 를 설치하기 위한 작업을 하기로 마음을 먹게 되었다.

필자가 사용할 USB 는 Sandisk Cruzer micro 8GB 이다.

 

그림 1. Sandisk Cruzer micro 8GB for USB 2.0

아무래도 해외 메이커이다 보니 폭넓은 사용자층으로 인해서 다양한 설치정보를 공유할수 있다는 장점이 있다. 

Sandisk Cruzer micro 8GB (이하 Sandisk USB로 약칭) 를 USB 포트에 연결하면 다음의 U3 창이 뜬다.

 

그림 2. USB 포트 연결시 초기 화면

 

윈도우 탐색기를 살펴보자.

 

I: (U3 System), J: (이동식 디스크) 2개의 드라이브가 새로 생긴 것을 볼 수 있다.

위에서 알수 있듯이 Sandisk USB 는 CD-ROM 영역과 일반 USB 영역 2개를 가지고 있다. 그냥 무턱대고 USB Disk Format 툴을 사용하면, CD-ROM 영역까지 삭제되므로

가능한 한 기존의  CD-ROM 영역을 살리면서 작업을 해나가기로 해보자.

 

대략 다음에 과정을 거친다.

 

1. GRUB4DOS 설치.

2. menu.lst 편집

3. Windows XP SP3.ISO 복사

4. 부팅 테스트. 

 

1. GRUB4DOS 설치.

 

 그림.

 

 

 

2. menu.lst 편집

 

3. Windows XP SP3.ISO 복사

 

4. 부팅 테스트

어떤 컴퓨터에서는 부팅이 잘 되는데 어떤 컴퓨터에서는 부팅이 되지 않는 것이다.

( 이런~ 욱시랄 ~ USB 가 사양을 타나 ??? )

나중에 알아본바 BIOS 회사에 따라서 되고 안되고 하는거였다. Phoenix BIOS와 Award BIOS 둘 다 테스트 해본 결과 아래와 같았다.

 

 

 Award BIOS

 Phoenix BIOS

 BIOS 내 인식

 USB-HDD

 USB-ZIP

 부팅 유무

 O

 X

 

위 표를 봤을때 USB-ZIP 을 USB-HDD 로 인식하게끔 하면 혹시 부팅이 되지 않을까?

라는 생각이 들지 않는가?

 

 아래 표는 Technet 에서 발췌한 FAT32 영역 중 확장 바이오스 파라미터 블럭의 설명이다.

위 표를 보면 윈도우즈 2000에서 인식할려면 0x42 부분의 값이 0x28 이나 0x29 로 되어 있어야 한다는 것을 알수 있다. 즉 0x29 로 되어 있으면 USB-ZIP 으로 인식하는 것이다.

이 부분을 0x00 으로 바꾸면 USB-HDD 로 인식이 되게 할 수 있는 것이다.

0x00 으로 되어 있을때 반대로 0x29 로 바꾸면 USB-ZIP 으로 인식하게 된다.

 

 

 

위 처럼 0x42 부분의 값을 0x00 으로 바꿔주고 저장을 한다.

그리고 테스트를 해봤더니 OK~ ㅋㅋㅋ

 

 

정복 터보 C #1

Posted by Programmer™
2010. 2. 15. 22:54 카테고리 없음

>>> 정복 터보 C <<<

                제1회  기억부류(storage class)의 정복

                   글/임인건 (서울대 기계공학과3)


---------------------------------------------------------------------
  1  본론에 앞서
---------------------------------------------------------------------

    요사이 C 언어가 무슨 전염병이나 된둣이 한창 퍼지고  있다.  컴퓨터
언어를 좀 안답시는 사람치고 주위에서 이빨에 힘주고 내뱉는 "씨-이"라는
소리를 들어보지 않은 사람은 없을 것이다. 컴퓨터 언어 중에서  더  이상
간단할 수 없는 이름을 가진 C는, 고급 어셈블러라고 불릴만큼 언어  자체
로 봐서도 비교적 콤팩트하다. 그렇다면 과연 뭐가 그리 좋길래  너도나도
C를 배우고 싶어하는가? 그럼에도 불구하고 너도나도 C가  어렵다고  학을
떼는 이유는 도대체 어디에 있는가? 그 이유와 해결 방법을  딱  뿌러지게
밝힘으로써 노력하는 자, 그 누구든 C 언어에 도통할 수 있는 길을 앞으로
독자 여러분께 명확히 제시하고자 한다.
    여러분은 터보 툴박스 시리즈을 기억하는지 모르겠다. 지난 '89.4월호
를 마지막으로 그 시리즈가 마감되었는데, 그 이후 5월호에  잠깐  이름을
내비친 다음에 필자는 마소에서 손을 떼고 감감 무소식이 되버렸다.  그간
필자는 마소를 잠시 멀리하고 방안에 꽁꽁 틀어 박혀서 칩거하고  있었다.
그러면서 뭔가를 열심히 끙끙대며 연구하고 있었는데, 그게 바로 "터보  C
정복의 길"이었다. 이제 그 연구가 거의 마무리되어 가시적이고 묵직한 모
종의 결실로 맺어질 찰라에 있다. 그래서 그 결실 중에서도 알짜만을 골라
한정된 지면을 빌어 마소 독자 여러분과 우선적으로 나눠 먹고자 한다. 그
러면 일단 이 글의 수준과 성격부터 분명히 짚고 넘어가기로 하자.

    C 정복의 길을 아래와 같이 5단계로 나눠보면,  제2단계  "기억부류의
구분"에서 출발하여 제3단계 "포인터의 완전 정복"을 이룸으로써  제4단계
의 표준 라이브러리 함수들을 충분히 활용할 수 있는 기초 능력을  배양한
다는 것이 이 글의 최종 목표가 되겠다(제5단계는 날고  기는  도사들이나
입문하는 과정이므로 보통 사람에게는 해당 사항이 없다).

---------------------------------------------------------------------
제1단계  변수, 상수, 데이터형, 매크로 상수, 연산자,
          간단한 문자열 취급법, 제어문과 루프, 함수 작성법
제2단계  기억부류(storage class)의 구분, 모듈별 분할 컴파일,
          전처리기(preprocessor)와 매크로 함수
제3단계  포인터, 구조체(structure)
제4단계  표준 라이브러리 함수
제5단계  메모리 모델, 혼합 언어 프로그래밍
---------------------------------------------------------------------

    그 다음으로 C의 초보자들이 C를 공부하다가 결국 C를 포기하는  데까
지의 시나리오를 살펴보면 대충 이렇다. 먼저 제1단계는 나무랄  데  없이
의욕적으로 열심히 독파해 나간다. 이 단계는 다른 언어를 공부하는  방식
과 별반 다를 것이 없으므로 대부분의 노력하는 초보자들은 큰 어려움  없
이 끝마친다.
    그러다가 제2단계로 접어들면서 왕성하던 의욕은 약간의 동요와  함께
점차로 흔들리기 시작한다. 기억부류를 위시해서 전처리기와 매크로  함수
등등 바야흐로 C를 특징짓는 생소한 개념들이 여기저기서 쉴 새 없이 튀어
나오기 때문이다.
    이렇게 흔들거리던 의욕은 제3단계 포인터로 접어들면서 완전히  휘청
거리게 된다. "도대체 뭘 주장하는 건지 하나도 모르겠다"고 투덜투덜대는
소리를 책 한 페이지 넘어가기가 무섭게 연발 또 연발한다. 결국에 가서는
처음에 그렇게도 왕성하던 의욕이 포인터의 수렁에서  무참히  좌초당하고
만다. 물론 구조체 같은 건 건너 뛰기가 바쁘다. 아무리 노력해도, 골백번
읽어도 이해가 안 가는 데는 별 수가 없는 것이다.
    이처럼 C에서 가장 난해한 부분인 제3단계에서 좌초함으로써  제4단계
의 막강한 표준 라이브러리 함수들을 제대로 써먹어 보지도 못하고, "나한
테 C는 도저히 안 되겠어!"라고 체념하면서 중도 포기하게  되는  것이다.
솔직히 말해서 제3단계의 포인터 부분에서 좌초하게 되는 이유로서 시중에
나온 C 입문서의 책임도 결코 작다고 할 수 없다. 왜냐하면 일부 C 입문서
들이, 극단적으로 말해서, 가장 난해한 부분을 가장 간단하게  "요약"해버
리는 수가 왕왕 있기 때문이다.
    어쨌든 이 글은 앞서 얘기한 것처럼 제3단계에서 좌초한 사람을  위한
일종의 "패자부활전"을 염두에 두고 제2단계부터 써나갈  생각이다.  다시
말해서 이 글은, C를 공부하다가 중도에서 포기한 사람이나 일단 한 번  C
를 전반적으로 훑어봤지만 아직도 뭔가 깨림직하여 도통 감이  안  잡히는
사람을 주된 대상으로 한다. 그러므로 이 글은 절대로 초보자를 위한 것이
아니다. 자신이 초보자라고 생각하는 사람은 지금까지 마소에 연재한 C 입
문 기사 또는 시중에서 구할 수 있는 C 입문서를 가지고  최소한  제1단계
정도는 공부해주셔야 할 것이다.


---------------------------------------------------------------------
  2  ANSI C와 pre-ANSI C
---------------------------------------------------------------------

    한편 이 글에서 사용하는 C 컴파일러로서 지명도가  높은  볼랜드사의
터보 C를 쓰기로 한다. 그것은 일반적인 유닉스 C에 대해 설명하는 것보다
IBM-PC에서 돌아가는 특정 컴파일러를 대상으로 한정하는 것이 보다  정확
하고 명확한 설명을 하는데 큰 잇점을 가져다 주기 때문이다.
    그리고 터보 C는 몇 년 전에 정립된 ANSI C 설계 표준(더욱  새로와진
C 규격이라고 생각하면 됨)을 충실하게 따르기 때문에 이 글도  ANSI  C를
바탕으로 하여 예제나 기타 모든 설명을 이끌어 나갈 작정이다. 따라서 AN
SI C를 위주로 하지 않은 C 입문서를 읽은 독자는 ANSI C의  새로운  함수
정의 방식 등등 여러가지 면에서 약간의 생소함이 있을지 모르겠는데,  그
것은 어느 정도 시간이 흐르다 보면 눈에 익을 테니까 큰 걱정을 하지  않
아도 되리라 본다.

    우선 급한대로 ANSI C와 pre-ANSI C(ANSI 표준이 나오기 전의 C) 간의
차이점 중 가장 눈에 띄는 차이점 세가지만 알아보도록 하자. 첫번째로 AN
SI C에서는 void 함수라는 것을 제공한다. 예를 들어 main 함수를  작성하
려면 pre-ANSI C에서는 아래와 같이 한다. main 함수는 매개변수와 리턴값
이 없으므로,

main()
{
    ......
}

라고 한다. 그러나 ANSI C에서는 void라는 키워드를 써서 아래와 같이  나
타낸다.

  +-------------------- 리턴값이 없음을 나타낸다.
  |
void main(void)
{          |
    ...... +----------- 매개변수가 없음을 나타낸다.
}

    그 다음으로 ANSI C에서는 함수의 매개변수 리스트를  함수명  다음의
괄호안에 기술하는 특징이 있다. 예를 들어 두 매개변수의 값을  교환해주
는 swap 함수를 작성해보자.

---------------------------------------------------------------------
pre-ANSI C                ANSI C
---------------------------------------------------------------------
                                 각 매개변수마다 데이터형을 따로 지정
                                       +----------+
swap(pa, pb)         +--- void swap(double *pa, double *pb)
double *pa, *pb;     |    {         +--------------------+
{                    |        double temp;  매개변수 리스트라고 부름
    double temp;     |
                     |        temp = *pa;
    temp = *pa;      |        *pa = *pb;
    *pa = *pb;       |        *pb = temp;
    *pb = temp;      |    }
}                    |
                     +--- 이 부분을 함수 원형이라 부른다.
---------------------------------------------------------------------

    오른쪽과 같이 매개변수 리스트를 지정하는 방식의 장점은 함수를  호
출했을 때 컴파일러가 매개변수의 데이터형을 검사해준다는 것이다.  예컨
대 double형 변수 a, b의 값을 교환하기 위해,

    swap(&a, &b);

라고 할 것을 실수로 번지 연산자 &를 빠뜨려서,

    swap(a, b);

라고 하면 ANSI C에서는 에러가 발생하지만, pre-ANSI C에서는 매개변수의
데이터형 검사를 행하지 않으므로 에러가 전혀 발생하지 않으며 따라서 심
각한 벌레(bug)가 될 수 있다.
    그 밖에 ANSI C에서는 이와 같은 매개변수의 데이터형 검사를  행하기
때문에, 프로그램 내에 작성한 함수가 여러 개 있을 경우 파스칼과 마찬가
지로 어떤 함수를 호출하려면 반드시 그 함수가 전에 이미 정의되어  있어
야 한다. 즉 함수 func_a가 func_b를 호출하고 다시 func_b가 func_c를 호
출하면 프로그램 내에 각 함수를 func_c, func_b, func_a의 순으로 위치시
켜야 한다.
    이러한 함수 배치에 대한 제한을 피하기 위해 ANSI C에서는 함수 원형
에 의한 함수 선언을 지원하고 있다. 이는 파스칼의 forward 선언과 그 개
념이 거의 같다. 함수를 선언하는 방법은 앞의 예에 표시해 놓은 함수  원
형에다가 세미콜론을 붙여서 프로그램 선두에 두면 된다. 예를 들어서 swa
p 함수를 선언하려면,

                                 +------ 함수 원형에 세미콜론을
                                 |       붙여야 한다.
void swap(double *pa, double *pb);
|                               |
+-------------------------------+
  함수 원형(function prototype)

    이렇게 해두면, 예컨대 함수 func_a, func_b, func_c를 프로그램 선두
에다가 선언해두면, 함수 본체는 그 함수 선언 이후의 아무데나 순서에 상
관없이 둘 수 있다. 즉 func_a, func_b, func_c와 같은  순서로  위치시킬
수도 있다.
    이와 같이 프로그램 내에 쓰인 모든 함수는 가급적 함수 선언을  프로
그램 선두에 해두는 것이 바람직하다. 따라서 프로그램 내에서 작성된  함
수는 물론 함수 선언을 해두어야 하고, 또한 printf, gets 등과 같은 터보
C의 표준 라이브러리 함수를 사용할 경우에도 그 함수들이 선언되어  있는
터보 C의 해당 표준 헤더 화일을 프로그램 선두에서  포함(include)시켜주
는 것이 바람직하다(단 main 함수만은 예외로 함수  선언이  전혀  필요없
다).
    서론이 다소 길어졌는데, 이제 이 글의 본론인  "기억부류의  정복"에
들어가기로 한다. 지면이 한정되어 있기 때문에 글이 다소 빡빡하질  테니
까 마음을 가다듬고 한 글자 한 글자 또박또박 머릿속에  새기기  바란다.
그냥 얕잡고 덤벙덤벙 대며 읽다가는 글자가 전부 눈에서  반사되어  튕겨
나갈테니 하는 말이다. 그럼 건투를 빈다.

다음 글로 계속 이어집니다.
turbo28 터보이빨 임 인 건

계속하시겠습니까? (Y/n) >>


임인건   (turbo28 )
[강좌] C포인터1-2: 기억부류의 정복           03/06 00:19   159 line

---------------------------------------------------------------------
  3  지역변수 vs. 자동변수, 전역변수 vs. 외부변수
---------------------------------------------------------------------

    파스칼에는 전역변수(global variable)라는 것이 있다. 전역변수란 말
그대로 프로그램의 모든 부분에서 자유롭게 사용할 수 있는 변수이다. C에
는 파스칼의 전역변수와 그 개념이 동일한 외부변수라는 것이 있다.  파스
칼과 C의 변수를 비교해보자. 용어의 차이일 뿐 그 개념은 동일하다.

<표 1> 파스칼과 C의 변수
------------------------------------------------
   파스칼                  터보 C
------------------------------------------------
   지역(local)변수         자동(automatic)변수
   전역(global)변수        외부(external)변수
------------------------------------------------

    앞서 서론에서 예로 든 swap 함수에서 선언(정의)된 temp라는  변수가
자동변수에 해당한다. 자동변수와 외부변수의 특징은 다음과 같이  비교된
다. 아무래도 한 구절 한 구절 암기하는 편이 좋을 성 싶다.

<표 2> 자동변수와 외부변수의 비교
---------------------------------------------------------------------
[1] 변수를 정의하는 위치
  * 자동변수는 함수 내부의 선언부에서 선언(정의)한다.
  * 외부변수는 함수 외부 아무 위치에서나 정의한다.

[2] 변수의 사용 범위:
  * 자동변수는 선언(정의)된 함수 내부에서만 사용 가능하다.
  * 외부변수는 프로그램 전체에 걸쳐 모든 함수에서 사용 가능하다.

[3] 변수의 수명:
  * 자동변수는 함수가 실행됨과 동시에 생성되며 함수가 실행될 동안에만
    존재한다. 즉 함수의 실행이 종료됨과 동시에 소멸된다. 함수의  실행
    이 종료되는 즉시 소멸되므로 메모리를 절약하는 효과를 가져온다.
  * 외부변수는 프로그램이 실행되는 동안 항상 존재하며 프로그램의 실행
    이 종료될 때까지 결코 소멸되지 않는다. 외부변수가  저장하고  있는
    값도 사용자가 변경하지 않는 한 프로그램의 실행이 종료될 때까지 그
    대로 유지된다.

[4] 변수를 정의할 때 초기치을 지정했을 경우:
  * 자동변수는 함수가 실행될 때마다 초기화된다.
  * 외부변수는 프로그램이 실행됨과 동시에 단 한 번만 초기화된다.

[5] 변수를 정의할 때 초기치를 지정하지 않았을 경우:
  * 자동변수는 모두 쓰레기값(garbage)을 가진다. 따라서 사용자가  어떠
    한 방법으로든지 초기화한 다음 사용해야 한다. 외부변수는 모두  0으
    로 초기화된다.

[6] 저장되는 장소:
  * 자동변수는 동적인 스택(stack)상에서 생성, 저장, 소멸된다.
  * 외부변수는 스택과 별개인 정적 데이터 영역(<그림 1> 참고)에 저장된
    다.
---------------------------------------------------------------------

<그림 1> 소형(Small) 메모리 모델일 때의 메모리맵
---------------------------------------------------------------------

세그먼트 레지스터와       메모리맵                   사용도
세그먼트의 크기

                |                           |
                +---------------------------+
          CS--+-|                           |
    최대      | |           코드            |
64K 바이트까지| |                           |
              +-|                           |
                +---------------------------+--+  외부변수,
    DS,SS,ES--+-|      초기화된 데이터      |  |  정적변수,
              | +---------------------------+  +--문자열 상수가
              | |     비초기화된 데이터     |  |  저장되는 곳
              | +---------------------------+--+
              | |        근거리 힙          |  +--동적 메모리 할당
    최대      | |---------------------------|--+
64K 바이트까지| |                           |
              | |        자유 공간          |
              | |                           |
              | |---------------------------|--+--SP
              | |                           |  |  자동변수가 위치
              +-|           스택            |  |
                +---------------------------+--+--Starting SP
              +-|         원거리 힙         |  |
              | |                           |  +--동적 메모리 할당
              | |---------------------------|--+
    남은      | |                           |
메모리 끝까지 | |                           |
              | |         자유 공간         |
              | |                           |
              | +---------------------------+

  * 초기화 또는 비초기화된 데이터의 영역이 정적  데이터(static  data)
    영역이다.

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

    그런데 파스칼의 지역변수에 해당하는 C의 자동변수의 경우에는 "선언
"과 "정의"를 구분할 필요가 없었다. 왜냐하면 자동변수는 정의가 곧 선언
이고 선언이 곧 정의이기 때문에, 정의라는 용어를 사용하지 않고  관습상
선언이라는 용어를 사용하는 것이 일반적인 경향이다.
    그래서 좀전에 자동변수 temp를 언급할 때, "변수 정의"라는 용어와 "
변수 선언"이라는 용어를 동일한 뜻으로 간주하여 "변수를 선언(정의)한다
"라고 했다. 그러나 외부변수나 함수의 경우 "정의(definition)"와  "선언
(declaration)"이라는 용어가 명백히 구분지어져 사용되므로 그 뜻을 명확
하게 이해하는 것이 대단히 중요하다.


---------------------------------------------------------------------
  3  정의(definition)와 선언(declaration)의 구별
---------------------------------------------------------------------

* 정의와 선언의 대상은 변수와 함수 두 가지로 정한다.
   이 글에서는 변수와 함수만 정의와 선언의 대상으로 간주한다.

* 정의는 "만든다"는 의미를 가지고 있다.
* 선언은 "알린다"는 의미를 가지고 있다.

* 정의는 변수나 함수의 특성을 언제나 완전하게 지정해 주어야 한다.
   왜냐하면 완전하게 지정해야만 "만들 수" 있기 때문이다.
* 선언은 변수나 함수의 특성 중 필요한 것만 지정할 수 있다.
   왜냐하면 변수나 함수를 사용하는데 필요한 정보만 "알려주면" 되기 때
   문이다. 그러므로 필요없는 정보는 생략할 수 있다.

* 따라서 배열의 크기나 매개변수 리스트는 정의에 명시해야 한다.
* 따라서 배열의 크기나 매개변수 리스트는 선언에서 생략 가능하다.
   단, 생략하는데 약간의 제약이 따른다.

* 정의는 변수나 함수를 위한 저장 장소를 메모리상에 할당하도록 한다.
* 선언은 변수나 함수의 특성을 컴파일러에게 알려주기만 한다.
   특성은 변수나 함수의 데이터형, 배열의 크기, 함수의 매개변수 리스트
   등등을 포함해서 변수나 함수에 대한 모든 정보를 말한다.

< 하나의 변수나 함수에 대해 >
* 정의는 만드는 것이므로 프로그램 전체를 통해 단 한 번만 이루어진다.
* 선언은 알리는 것이므로 프로그램 전체를 통해 여러 번 중복되어도  좋
   다. 여기서 프로그램 전체란 프로그램이 둘 이상의 모듈로 구성되어 있
   을 때 그 모든 모듈을 포함해서 일컫는다.

* 정의는 언제나 선언을 겸한다!
* 선언은 결코 정의를 겸할 수 없다.

* 자동변수의 경우 정의와 선언은 구별되지 않는다.
* 외부변수와 함수의 경우 정의와 선언은 명확하게 구별된다.

* 따라서 자동변수의 경우 구별없이 "변수를 선언 또는 정의한다"고 말한
   다.
* 따라서 외부변수의 경우 "변수 선언"과 "변수 정의"는 서로 다르다.
* 따라서 함수의 경우 "함수 선언"과 "함수 정의"는 서로 다르다.

< 정의에 의한 선언 또는 그냥 선언이 미치는 범위(scope) >
* 함수 내부에서 선언이 이루어진 경우 함수 내부에만 알려진다.
* 함수 외부에서 선언이 이루어진 경우 선언이 이루어진 화일  내(프로그
   램 전체가 아님)에만 알려진다. 별다른 조치를 취하지 않으면 다른  화
   일에 선언이 알려지지 않는다.
* 선언은 해당 변수나 함수가 실제 사용되기 전에 이루어져야 한다. 그렇
   지 않으면 변수의 경우 "Undefined symbol" 에러가 발생하며 함수의 경
   우 "Type mismatch in redeclaration"에러가 발생할 수 있다.

다음 글로 계속 이어집니다.
turbo28 터보이빨 임 인 건

계속하시겠습니까? (Y/n) >>


임인건   (turbo28 )
[강좌] C포인터1-3: 기억부류의 정복           03/06 00:37   263 line

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

  4  외부변수의 정의(definition)

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



    외부변수를 정의하는 방법은 자동변수를 선언(정의)하는 방법과  거의

유사하다. 단 한 가지, 정의하는 위치가 함수 내부가 아니라 함수  외부라

는 점만 다를 뿐 나머지는 똑같다. 그러므로 어떤 변수가  정의되었을  때

그 정의된 위치가 함수 내부이면 자동변수, 함수  외부이면  외부변수라고

보면 틀림없다.



<그림 2> 외부변수와 자동변수의 정의 방법 비교

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

int function1(int param); --- 함수 선언

......



char *format;     -+

int number;        +- 외부변수를 정의

double value[10]; -+  이후의 모든 함수에서 사용할 수 있음



void main(void)

{

    int temp;          -+- 자동변수를 선언(정의)

    float realnumber;  -+   main 함수 내에서만 사용 가능.



    ......

    temp = function1(10);

    ......

}



char mychar; ---- 외부변수를 정의

                  이후의 모든 함수에서 사용할 수 있음

                  main 함수에서는 사용할 수 없음에 주의

int function1(int param)

{

    char c; ---- 자동 변수를 선언(정의)

    float realnumber; ---- main 함수 내의 똑같은 이름을 가진

                           realnumber와는 전혀 상관 없는

    ......                 별개의 자동변수

    c = mychar & 0x7f;

    ......

}

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



    <그림 2>를 이해하는데 별 다른 무리가 없으리라 믿고 더 이상 부연하

지는 않겠다. 여기서는 외부변수를 정의할 때 지켜야할 관례(관습) 한  가

지만 알아보도록 하자.



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

[관례]  외부변수는 함수 선언과 같이 화일의 선두에서 정의하도록 한다.

         즉 화일 내의 어떤 함수라도 정의되기 이전에 외부변수를 정의하

         는 것이 좋다.

             <그림 2>의 mychar 외부변수처럼 함수들 사이에서  정의하는

         것은 바람직하지 않다. 왜냐하면 차후에 main 함수에서 mychar를

         사용할 경우 에러가 발생하기 때문이다.

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





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

  5  모듈별 분할 컴파일과 외부변수의 선언

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



    이제 외부변수의 선언에 대하여 알아보자. 외부변수를 선언하는  이유

는 한 마디로 모듈별 분할 컴파일(separate compilation)을 가능하게 하기

위함이다. 보통 프로그램의 크기가 어느 정도 이상(대략 500행  이상)으로

커졌을 경우 하나의 소스 화일 안에 프로그램 전부를 담는 것은 상당히 비

효율적이다. 그것은 컴파일하는 데 소요되는 시간이 무시할 수 없을  만큼

걸리기 때문이다.

    대개 500행 정도 되는 비교적 긴 프로그램에 있는 벌레를 완전히 제거

하기 위해서는 컴파일을 수십 번, 꼬이면 백수십 번까지도 해야 하므로 소

스 화일의 크기가 크면 클수록 컴파일 효율이 극도로 저하된다. 따라서 긴

하나의 소스 화일을 작은 소스 화일 여러 개로 분할하여 컴파일하는  것이

여러모로 좋다. 그렇게 분할 컴파일을 통하여 각각의 화일마다 독립적으로

벌레를 제거한 다음 최종적으로 링크 과정을 거쳐 실행 화일을 만들면  되

는 것이다. 이렇게 하나의 프로그램을 몇 개의 소스 화일에  나누어  담을

때 각각의 소스 화일을 그 프로그램의 모듈(module)이라고 부른다.

    C는 원래부터 모듈별 분할 컴파일을 지원해오던  언어이다.  파스칼의

경우 터보 파스칼 3.0 이전 버전에서는 모듈별 분할 컴파일이 지원되지 않

다가 터보 파스칼 4.0에 이르러서야 유닛(unit)이라는 개념으로  지원되기

시작했다. 모듈별 분할 컴파일의 가장 큰 장점은 말 그대로 각각의 모듈을

독립적으로 컴파일할 수 있다는 점이다. 따라서 어느 한 모듈에 에러가 발

생했을 경우 전체 모듈을 컴파일할 필요가 없이 에러가 발생한 모듈만  컴

파일할 수 있다. 그러므로 컴파일 시간이 크게 단축됨과 동시에  벌레잡기

(debugging)에도 그만이다.



    여기까지 모듈별 분할 컴파일의 효용에 대하여 알아보았다.  다음으로

모듈별 분할 컴파일을 하려면 외부변수를 선언할 필요가 있음에 대하여 알

아보자.

    하나의 프로그램을 여러 개의 모듈로 나눌려면 각 모듈 간의 정보  교

환이 필요하다. 특히 외부변수에 대한 정보 교환이 절실히 요청된다. 따라

서 각각의 모듈에서 사용할 외부변수에 대한 정보를 어떻게 해서든지 각각

의 모듈마다 알려주어야 할 것이다. 설명을 이해하기 좋도록 하기 위해 예

를 들어서, 전체 프로그램이 source1.c, source2.c, source3.c라는 화일명

을 가진 모듈로 분할되어 있고 source1.c 모듈에  mylove라는  외부변수가

정의(선언이 아님)되어 있다고 하자.



<그림 3> 각각의 모듈에서 사용할 외부변수 정의

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



            외부변수 mylove를 정의                 source1.c에 정의된

                |                                     외부변수를 사용

source1.c       |      source2.c              source3.c           |

+---------------+-+    +-----------------+    +-----------------+ |

| int mylove; --+ |    | int yourlove[3];|    | int func2(.....)| |

|                 |    |                 |    | {               | |

| void main(void) || int func1(.....)|    |     ......      | |

| {               |    | {               |    |     mylove = 1;-+-+

|     ......      |    |     ......      |    |     ......      |

| }               |    | }               |    | }               |

|                 |    |                 |    |                 |

| void sub1(void) |    | void sub2(void) |    | void sub3(void) |

| {               |    | {               |    | {               |

|     ......      |    |     ......|    |     ......      |

| }               |    | }               |    | }               |

+-----------------+    +-----------------+    +-----------------+

성공적으로 컴파일됨  성공적으로 컴파일됨  "Undefined symbol"에러 발생



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



    그런데 외부변수는 앞에서 언급했듯이 단 한 번만 정의할 수 있다. 그

러므로 하나의 외부변수에 대한 정의는 하나의 모듈 안에서 단 한 번만 이

루어진다. 즉 mylove는 source1.c 내에서 단 한 번만 정의된다. 이때 정의

는 언제나 선언을 겸하므로 외부변수가 정의되어 있는 모듈  내부에는  그

외부변수가 "알려진다". 따라서 mylove는 source1.c 내에서  사용  가능하

다.

    그러나 선언의 영향이 미치는 범위는 하나의 모듈로 한정되어  있어서

mylove의 정의만으로는 다른 모듈에 그 외부변수의 존재를 알릴  수가  없

다. 즉 source2.c나 source3.c 같은 다른 모듈에서 mylove를 사용할 수 없

다는 뜻이다.

    <그림 3>에서 mylove는 source1.c와 source3.c에 쓰인다. 그러므로 각

각의 모듈을 컴파일해보면 source1.c와 source2.c는 성공적으로  컴파일되

지만 source3.c는 "Undefined symbol" 에러를 내고만다. 왜냐하면  외부변

수 mylove의 존재가 source3.c에 알려지지 않았기 때문이다.

    그렇다고 source3.c에 mylove를 중복해서 정의해  놓으면  컴파일이야

물론 성공적으로 되지만 나중에 세 모듈을 링크할 때 source1.c의  mylove

와 source3.c의 mylove가 충돌을 일으킬 수 밖에 없다. 이럴 때 정의는 하

지 않고 단순히 알리기만 하는 "선언"이 필요한 것이다. 선언은  중복되어

도 좋다고 앞에서 분명히 언급했음을 상기하기 바란다.



    외부변수의 선언은 키워드 extern을 써서 아래와 같이 한다.



extern 데이터형 변수명1, 변수명2, ......;



    변수 정의 방법과 비교해 볼 때 문장의 선두에  extern이란  키워드를

삽입한 것을 제외하고는 거의 유사한 것처럼 보인다. 그러나 선언은  필요

한 정보만 제공해도 된다는 특징이 있기 때문에 정의보다는  더  간단하게

기술할 수 있다. 간단하게 선언하기 위해 생략할 수 있는 두 가지 예는 배

열의 크기와 함수의 매개변수 리스트이다.

그런데 함수의 매개변수 리스트는 매개변수의 데이터형 검사를 위해  가급

적 생략하지 않는 것이 좋기 때문에 실제로는 배열의 크기만 생략할 수 있

다고 보는 편이 바람직하다. 예를 들어 배열의 정의가 아래와 같을 때,



int array[100];



    위의 배열을 선언하고자 할 경우 배열의 크기를 생략할  수  있다(단,

다차원 배열일 때는 약간의 제약이 따른다). 그러므로



extern int array[100];

extern int array[];



    위의 두 문장은 동일한 선언이다. 그런데 관습적으로 간단한 extern i

nt array[]의 선언을 주로 사용한다.

    자, 그럼 외부변수의 선언을 사용하여 <그림 3>의 모듈을 수정해보자.

선언은 정의와 마찬가지로 각 모듈의 선두부분에 하는 것이 좋다. 이 점을

염두에 두고 <그림 3>을 수정하면 아래의 <그림 4>와 같이 된다.



<그림 4> 그림 3의 외부변수의 선언을 수정

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



                              외부배열 yourlove를 정의

                                           |

    외부변수 mylove를 정의                 |  외부변수 mylove를 선언

                |                    |                      |

source1.c       |      source2.c           |  source3.c           |

+---------------+-+    +------------------+|  +-----------------+ |

| int mylove;---+ |    | int yourlove[3];-++  | extern int      | |

|                 |    |                  |   |     mylove; ----+-+

| extern int      |    |                  |   |                 |

|     yourlove[]; |    |                  |   | int func2(.....)|

|                 |    |      |   | {               |

| void main(void) |    | int func1(.....) |   |     ......      |

| {               |    | {                |   |     mylove = 1; |

|     ......      |    |     ......       |   |     ......      |

| }               |    | }                |   | }               |

|                 |    |                  |   |                 |

| void sub1(void) |    | void sub2(void)  |   | void sub3(void) |

| {               |    | {                |   | {       |

|     ......      |    |     ......       |   |     ......      |

| }               |    | }                |   | }               |

+-----------------+    +------------------+   +-----------------+

성공적으로 컴파일됨    성공적으로 컴파일됨    성공적으로 컴파일됨



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



    외부변수의 선언 규칙에 대해서는 이야기가 다 끝났다. 남은 것은  선

언 방법상의 테크닉적인 문제이다. 외부변수의 갯수가 한두  개  정도라면

모르지만 갯수가 10개 정도만 넘어가도 두 가지 짜증나는  문제가  발생한

다.

    그것은 외부변수를 사용하는 각각의 모듈마다 일일이  그  외부변수를

선언해주어야 한다는 점과(외부변수가 정의된 모듈은 물론 선언이  필요없

다), 만약 외부변수 중에 하나라도 수정해야 할 경우가 생기면 그  외부변

수의 정의와 선언을 포함하는 모든 모듈을 일일이 에디터로 읽어들여 번거

롭게 수정해주어야 한다는 점이다.

예를 들어 변수명 mylove를 loveofmine으로 변경하려면 source1.c  모듈과

source2.c 모듈을 모두 수정해주어야 한다. 이런 방법은 대단히  번거로울

뿐만 아니라 수정하다가 자칫 실수할 소지가 많으므로 아무래도 다른 방법

을 강구하는 것이 좋다. 이럴 때 #include문을 사용한 간단한 테크닉을 쓰

는 것이다.



    앞의 <그림 4>를 잘 살펴보면 source1.c 모듈에서 사용하지도 않는 yo

urlove라는 배열을 쓸데없이 선언했음에도 불구하고 선언은 중복 가능하다

는 이유로 인해 컴파일은 성공적으로 끝낼 수 있음을 알 수 있다.  이처럼

모듈 내에서 사용하지 않는 외부변수라도 선언은 얼마든지 할  수  있다는

점을 최대한 이용한다.

    우선 모든 모듈 내에 정의된 외부변수의 선언을 별도의 헤더 화일  내

에 모조리 모아 놓고, 그 다음 각각의 모듈에서 #include문으로  그  헤더

화일을 포함하도록 하는 것이다. 이렇게 되면 어떤 외부변수의 추가  또는

변경 사유가 생기더라도 각각의 모듈을 일일이 번거롭게 수정할  것  없이

외부변수의 선언들을 모아 놓은 헤더 화일만 손보면 된다.

    물론 헤더 화일을 사용하더라도 어차피 외부변수의  정의가  수정되면

그 외부변수를 사용하는 모든 모듈을 재컴파일해야 하지만, 각 모듈의  소

스를 일일이 수정해야 하는 번거로움은 덜 수 있게 되어 대단히 편리하다.

게다가 헤더 화일에 각 모듈이 가지는 함수의 선언들까지 모아 놓으면  금

상첨화일 것이다.

    <그림 4>를 헤더 화일을 사용하여 재구성하면 아래의 <그림 5>와 같이

된다. <그림 5>의 헤더 화일 hd.h에는 함수 선언도 포함시켰다.



<그림 5> 외부변수의 선언을 모아 놓은 헤더 화일

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



hd.h

+-----------------------+

| void sub1(void);      |

| int func1(......);    |

| void sub2(......);    |

| int func2(......);    |

| void sub3(......);    +-------------------------------------------+

|                       +---------------------+                     |

| extern int mylove;    |                     |                     |

| extern int yourlove[];|                     |                     |

+---------------------+-+                     |                     |

                      |                       |   |

source1.c             | source2.c             |  source3.c          |

+-----------------+   | +------------------+  | +------------------+|

| #include "hd.h"-+---+ | #include "hd.h" -+--+ | #include "hd.h" -++

|                 |     |                  |    |                  |

| int mylove;     |     | int yourlove[3]; |    | int func2(.....) |

|                 |     |                  |    | {                |

| void main(void) |     | int func1(.....) |    |     ......  |

| {               |     | {                |    |     mylove = 1;  |

|     ......      |     |     ......       |    |     ......       |

| }               |     | }                |    | }                |

|                 |     |                  |    |                  |

| void sub1(void) |     | void sub2(void)  |    | void sub3(void)  |

| {               |     | {                |    | {                |

|     ......      |     |     ......       |    |     ......       |

|}               |     | }                |    | }                |

+-----------------+     +------------------+    +------------------+

성공적으로 컴파일됨     성공적으로 컴파일됨     성공적으로 컴파일됨



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


다음 글로 계속 이어집니다.
turbo28 터보이빨 임 인 건

계속하시겠습니까? (Y/n) >>


임인건   (turbo28 )
[강좌] C포인터1-4: 기억부류의 정복           03/06 00:40   220 line

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

  6  정적변수(static variable)

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



  6.1 내부정적변수(internal static variable)



    자동변수는 그 수명이 영구적이지 못해서 함수의 실행이 종료되는  즉

시 소멸된다. 자동변수의 이러한 특징은 메모리의 절약이나 기타 여러가지

측면에서 볼 때 대단히 유용하지만, 어떤 상황 하에서는 변수가  소멸되지

않고 계속 남아있는 것이 더 좋을 때가 있다. 이럴 때 긴요하게 쓰이는 것

이 바로 내부정적변수(internal static variable)이다.

내부정적변수의 선언(정의)은 자동변수 선언문의 선두에 static이라는  키

워드를 붙이기만 하면 된다.



    static 데이터형 변수명, 변수명, ......;



                         +-----프로그램 실행시 단 한 번만 초기화된다.

    예)                  |

    static double pi = 3.141592;

    static int array[100];

                  |

                  +---------0으로 초기화된다.



    내부정적변수의 특징은 딱 한 가지만 제외하고는외부변수의  특징과

완전히 동일하다. 그 한 가지란, 외부변수는 프로그램 전체에  걸쳐  사용

가능한 전역변수이지만 내부정적변수는 반드시 함수 내부에서만 쓰이는 지

역변수라는 점이다. 그 외에는 외부변수의 특징과 똑같다. 그리고,



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

     내부정적변수는 외부변수의 특징을 가진 자동변수이다.

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



라고 생각하면 비록 정확한 표현은 결코 아니지만 내부정적변수에 대해 대

략적으로나마 감을 잡는데는 다소나마 도움이 되리라 본다.



  6.2 외부정적변수(external static variable)



    외부정적변수(external static variable)는 외부변수와  비교해볼  때

변수 사용 범위(scope)만 제외하고 완전히 동일하다.  외부변수는  자신이

정의된 모듈 이외의 모듈에 extern문을 써서 알릴 수 있다(즉 외부변수 선

언). 그러나 외부정적변수는 결코 알릴 수 없다. 즉 외부정적변수가  정의

된 모듈 내에만 알려진다. 따라서 외부정적변수는 자신이 정의된 모듈  내

에서만 사용 가능하고 다른 모듈에서는 사용이 불가능하다. 이 점을  감안

하면 외부정적변수의 특징을 아래와 같이 표현할 수 있다.



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

     외부정적변수는 특정 모듈 전용의 외부변수이다.

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



    다시 말해서 외부정적변수는 특정한 모듈 내에서만 사용할 뿐 다른 모

듈에는 알릴 필요가 없거나, 알려서는 안 될 때 사용하면 된다.  외부정적

변수의 정의는 외부변수를 정의할 때 문장 선두에 static이라는  키워드만

붙이면 된다.



static 데이터형 변수명1, 변수명2, ......;



예)



static float pi = 3.141592;

static int array[10];



    위의 정의에서 알 수 있듯이 내부정적변수와 정의하는 방법이  완전히

동일하다. 다만 정의하는 위치가 다를 뿐이다. 따라서 정적변수가 함수 내

부에서 정의되었을 때 내부정적변수, 함수 외부에서 정의되었을 때 외부정

적변수라고 보면 틀림없다.

    이 점을 고려하여 이 글에서 앞으로 특별히 명시해야 할 경우를  제외

하고는 "내부정적변수"나 "외부정적변수"라는 용어의 사용을 피하고  그냥

"정적변수(static variable)"라는 용어를 사용하기로 한다. 그 정적변수가

내부형인지 외부형인지는 정의되어 있는 위치를 봐서 판별하기 바란다.

    한편 외부정적변수는 모듈별 분할 컴파일을 하지 않는 한  거의  쓸모

없는 존재이다. 왜냐하면 프로그램 전체가 하나의 모듈로  구성되어  있을

경우, 외부변수와 외부정적변수가 전혀 구별되지 않기 때문이다. 왜  구별

되지 않는지는 곰곰히 생각해보면 이해가 갈 것이다.  다음의  정적함수도

마찬가지이다.

    그리고 이 글을 처음 쓸 당시에는 터보 C가 제공하는 Project-Make 기

능을 써서 모듈별 분할 컴파일의 예를 다뤄 볼 작정이었지만 글을  써나가

다 보니 지면 사정이 도저히 허락치 않아서 부득이 생략할 수 밖에 없음을

안타깝게 생각하는 바이다.

    또한 변수의 종류 중에는 지금까지 설명한 자동변수, 외부변수,  정적

변수 외에도 C만의 특이한 존재인 "레지스터변수"라는 것이 있는데 용도가

매우 제한되어 있는 관계로 이 글에서는 논하지 않겠다. 사실  레지스터변

수는 몰라도 전혀 지장이 없다.





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

  7  정적함수(static function)

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



    정적함수(static function)의 의미는 아래와 같다. 외부정적변수의 개

념과 매우 유사함을 알 수 있을 것이다. 정적함수의 용도도  외부정적변수

와 같다. 즉 어떤 함수가 특정한 모듈 내에서만 사용될 뿐 다른 모듈 내에

서는 전혀 사용되지 않을 때(또는 사용해서는 안 될 때) 그 함수를 정적함

수로 정의하면 되는 것이다.



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

     정적함수는 특정 모듈 전용의 함수이다.

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



    다음으로, 정적함수를 정의, 선언하는 방법은 다음과 같다.



* 정적 함수의 정의



static 함수형 함수명(매개변수 리스트)

{

    ......

}



* 정적 함수의 선언          +--- 함수 원형(prototype)

                            |

+---------------------------+-------+

static 함수형 함수명(매개변수 리스트);





    정적함수도 보통의 함수나 외부변수처럼 선언할 수 있다. 그러나 선언

이 불필요한 외부정적변수와는 달리 정적함수는 선언이 필요하다. 그 이유

는 "Type mismatch in redeclaration" 에러를 막기 위함이다. 물론 선언은

그 모듈 선두에서 행하는 것이 가장 바람직하다.

    그러면 <그림 5> 같이 프로그램을 구성할 때 정적함수의 선언은  과연

어디에 두어야 할까? 정적함수는 자신이 정의된 모듈 이외의 모듈에  자신

의 존재를 알릴 수 없으므로 <그림 5>의 hd.h와 같은 헤더 화일에  정적함

수의 선언을 두어서는 안 된다. 따라서 정적함수의 선언은 그 자신이 정의

된 모듈의 선두에 두는 것이 가장 바람직한 방법이다.





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

  8  기억부류(storage class)

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



    이번 달 연재의 부제목이 "기억부류의 정복"임에도 불구하고 처음부터

이제까지 기억부류라는 말을 거의 쓰지 않았는데 이제서야 비로소  기억부

류에 대하여 이야기하겠다.

    기억부류(storage class)라는 용어가 상당히 생소할 줄로 안다.  그러

나 말만 생소할 뿐 그 용어의 개념은 이미 다 익혔다. 일단  변수를  예로

들자. 변수의 종류는 크게 나누어서 자동변수,외부변수, 정적변수,  레지

스터변수(이 글에서는 설명하지 않았음)의 4가지 부류로 구분된다. 기억부

류(storage class)란 별 것 아니라 바로 이들 4가지 부류를 통틀어서 일컫

는 용어이다.

    기억부류는 <표 3>과 같이 그 변수나 함수의 저장 장소와 선언의 영향

이 미치는 범위에 따라 구분된다. 참고로 <표 3>에서 기억부류지정자(stor

age class specifier)란 auto, static, extern, register  등의  키워드를

총칭하는 용어임을 알아두기 바란다.





<표 3> 4가지 기억부류와 대응하는 기억부류지정자

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

기억부류지정자     변수                    함수

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

    auto           자동변수                  x

               (automatic variable)

    extern         외부변수              (외부)함수

               (external variable)

    static         정적변수               정적함수

               (static variable)     (static function)

    register     레지스터변수                x

               (register variable)

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

* auto 키워드는 항상 생략 가능하며 보통 생략한다.

* static, register 키워드는 생략할 수 없다.

* extern 키워드는 변수 선언에만 쓰인다.



    위의 <표 3>에 보이듯이 자동함수나 레지스터함수는 존재하지  않음을

알 수 있다. 16비트의 레지스터에 수백, 수천 바이트의 함수를 저장할  수

는 없는 일이며 또한 스택상에서 생성, 소멸하는 함수가 존재할 수도 없는

일이다. 따라서 보통 일반적인 함수는 기억부류로 따지자면 원래 모두  외

부형(external)이다. 다만 함수를 정의할 때 static 키워드를 쓰면 그  함

수가 정적함수가 될 뿐이다.

    함수는 2가지의 기억부류 밖에 없는데 반하여 변수는 다양한 기억부류

를 가진다. 왜냐하면 기억부류를 조합할 수 있기 때문이다. 아래에 가능한

조합 방식을 모두 선보였다. 아래에서 한 가지 유의할 것은 auto라는 키워

드이다. 사실 모든 자동변수는 e와 같이 auto 키워드를 써서 선언(정의)되

어야 한다. 그러나 다행히도 auto 키워드는 항상 생략 가능하기 때문에 여

태까지 우리는 d와 같이 auto라는 키워드 없이  자동변수를  선언(정의)할

수 있었다.





int a;        <--- 외부변수 a의 정의 겸 선언

                   (다른 모듈에 알려질 수 있다)

extern int b; <--- 외부변수 b의 선언

                   (통상 b는 다른 모듈에 정의되어 있을 것이다)

static int c; <--- 외부정적변수 c의 정의 겸 선언

                   (다른 모듈에는 알려지지 않는다)



void main(void)

{

    int d;          <--- 자동변수 d의 정의 겸 선언

    auto int e;     <--- 자동변수 e의 정의 겸 선언(auto는 생략 가능)

    static int f;   <--- 내부정적변수 f의 정의 겸 선언

    register int g; <--- 레지스터변수 g의 정의 겸 선언



    ......

}





    다음으로, 변수의 기억부류를 선택하는 요령에 대해서 알아보자. 변수

의 기억부류를 선택하는 데 있어서 기본 원칙은 다음과 같다. 왜 이런  원

칙이 정당한가 하는 이유는 독자 스스로 생각해보기 바란다.



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

[1] 피치 못할 경우를 제외하고는 가능한 한 자동변수를 택한다.

[2] 외부변수의 사용은 최대한 자제하고 공용성이 매우 높은 변수에  한해

    외부변수로 정의한다.

[3] 초기화가 꼭 필요하거나 공용성을 가지는 배열은 주로 외부형으로  정

    의한다. 초기화될 필요가 없거나 공용성이 거의 없는  배열은  가급적

    자동배열로 선언하도록 한다.

[4] 모든 외부변수(정적변수 포함)는 가능한 한 초기화를 한다.

[5] 외부변수는 가능한 한 읽기 전용(read only)으로 사용한다.

[6] 특정 외부변수의 값을 변경하는 함수는 가능한 한 하나의 함수로 제한

    한다.

[7] 자동변수의 값을 보존할 필요가 있을 경우 내부정적변수로 정의한다.

[8] 프로그램이 하나의 모듈로 구성되어 있을 경우 외부정적변수를 사용할

    필요는 전혀 없다.

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



    그 밖에 함수의 형식매개변수(formal parameter)는 기억부류로 따지자

면 자동변수에 해당되며, 상수 중에서 문자열 상수(string constant)의 경

우 저장 장소가 정적 데이터 영역이기 때문에 그 기억부류는 정적(static)

임을 참고하기 바란다.


다음 글로 계속 이어집니다.
turbo28 터보이빨 임 인 건

계속하시겠습니까? (Y/n) >>


임인건   (turbo28 )
[강좌] C포인터1-5: 기억부류의 정복           03/06 00:42   161 line

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

  9  다음에는

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



    이상에서 C의 기억부류에 대해 자세히 살펴보았는데, 이건 연습  게임

에 불과하다. 사실 이번 달 얘기는 다음 달의 얘기를 끌어내기 위한  전초

전 성격을 띄고 있어서 뚜렷하게 "바로 이거다!"하고 얻어 낼 성과는 그리

변변치 못할 것으로 여겨진다. 그러나 기억부류에 관한  사항을  철저하게

파악하고 있어야 앞으로 전개해 나갈 내용을 충분히 이해할 수 있게  된다

는 점을 명심하기 바라며, 다음 달부터는 대략 3회에 걸쳐 이번 연재의 하

일라이트인 "C의 대명사 포인터"에 관하여 집중적으로 탐구해볼 생각이다.

시중에 나와있는 어떠한 C 관계 서적보다도 한층  체계적이고  논리적이고

분석적으로 포인터의 모든 것을 하나도 남김없이 낱낱이 파해쳐 나갈 작정

이니 기대해도 좋을 성 싶다. 바야흐로 독자 여러분도 이제 포인터를 완전

히 정복할 수 있게 된 것이다!





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

  부록  덤으로

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



    필자가 이번 연재를 맡으면서 마소 편집부에 한 가지 물어본 게 있다.

그것은 마소의 독자들이 글의 내용을 떠나서 일반적으로 가장 선호하는 게

뭐냐는 물음이었다. 그랬더니 마소 편집부 왈, "뭔가 보여줘야 한다"는 응

답을 얻었다. 말인 즉 독자의 눈을 즐겁게 해주어야 한다는 것이다.  그렇

다면 눈을 즐겁게 해주는 가장 쉬운 방법이 무엇인가? 그건 바로 그래픽이

아닌가?

    마침 이번 달의 글이 다소 빠듯해서 변변한 예제 하나없던 차에 잘됐

다 싶어, 덤으로 볼만한 그래픽 예제를 하나 소개하기로 한다. 하기사  이

번 예제가 만들어 내는 그림이야 흔하게 본 것일테지만, 베이직이나  파스

칼이 아닌 터보 C에서 새로이 "실행시켜보는 재미" 또한 만만치  않으리라

본다. 일단─은 예제의 내용에 일체 신경쓰지말고 그저 실행이 된다는  사

실을 즐기기 바란다.

    우선 예제를 sombrero.c라는 화일명으로 입력부터 하기 바란다. 다 입

력하고 디스크에 세이브했으면, <Alt-F><O>키를 눌러  도스로  빠져나가서

현재 디렉토리(current directory)에 herc.bgi라는 그래픽 드라이버(graph

ics driver) 화일이 있는지 점검한다. 이 화일이 없으면 예제가  실행되지

않는다. EGA 사용자라면 그것 대신에 egavga.bgi라는 그래픽 드라이버  화

일이 필요하다. 점검했으면 도스 명령행에 exit⇔를 입력하여 터보 C 통합

개발환경(약칭 IDE)으로 되돌아온다.

그런 다음, 만약 독자의 터보 C가 버전2.0이라면, <F9>키를  눌러  컴파일

◎링크가 무사히 끝나는가 확인하고 <Ctrl-F9>키를 눌러서 예제를  실행시

킨다.

    만약 터보 C 1.5라면 아래 두 줄의 짤막한  내용을  sombrero.prj라는

화일명으로 입력한 뒤 <F2>키를 눌러 디스크에 세이브시킨다.



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

sombrero

graphics.lib

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



    이제 <Alt-P>를 눌러 "Project" 메뉴를 선택하고 곧이어 "Project nam

e" 항목을 택한다. 그러면 IDE가 프로젝트 화일명의 입력을 요구하는데 so

mbrero⇔라고 입력하면 된다. 그런 다음 <F9>키를 눌러 컴파일◎링크가 무

사히 끝나는지 확인하고 <Alt-R>키를 눌러 예제를 실행시킨다. 그러면  화

면 가득히 근사한 멕시코 모자가 그려질 것이다. 참고로 도(degree)단위의

각도인 매크로 상수 ZROTATE, YROTATE, XROTATE의 값을  수정하면  또다른

각도에서 바라본 멕시코 모자의 그림을 얻을 수 있다. 예를 들어  XROTATE

를 180.으로 변경하면 모자가 뒤집어진다.



<리스트 1> 그래픽 예제 프로그램

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

/* File SOMBRERO.C: Sombrero - HGC/EGA version */



#include <graphics.h> -+-그래픽 함수와 수학 함수의 선언이 들어있음

#include <math.h>     -+

                              +-----불린형을 정의

typedef enum {false, true} boolean;



void graph(double y, double z, int *plotted);     -+

void rotate3d(double xr, double yr, double zr,     | 함수 선언

              double *px, double *py, double *pz);-+



                              /*      |z        */  이 예제에서

#define SIZE 2.               /*      |         */  쓰인 3차원 좌표계

#define ZROTATE 11.           /*      |         */  그래픽 화면은

#define YROTATE 40.           /*      +------ y */  yz평면에 해당함

#define XROTATE 0.            /*     /          */

                              /*    /           */

                              /*   x            */



double function(double x, double y)     멕시코 모자를 나타내는

{                                         3차원 평면의 식

    double f;



    f = hypot(x, y) / 35.;

    if (fabs(f) < 1.e-5) return (40. * M_PI);

    else return (40. * sin(f * M_PI) / f);

}



void main(void)

{                       자동변수를 선언(정의)

    int graphdrive = DETECT, graphmode;

    int plotted = false; ---- 곡선의 시작점인지의 여부를 가림

    double x, y, z, x2, y2, z2; ---- 3차원 좌표

    double zr, yr, xr; ---- 각각 z축, y축, x축을 중심으로 하는 회전각



    initgraph(&graphdrive, &graphmode, "");



    zr = ZROTATE * M_PI / 180.; -+

    yr = YROTATE * M_PI / 180.;  | 라디안 값으로 환산

    xr = XROTATE * M_PI / 180.; -+



    for (x = -115.; x <= 115.; x += 5.) {

        for (y = -115.; y <= 115.; y += 5.) {

            z = function(x, y);

            x2 = x * SIZE; -+-- 좌표를 SIZE배만큼 확대

            y2 = y * SIZE;  |          z축, y축, x축을 중심으로 각각

            z2 = z * SIZE; -+                    |  회전

            rotate3d(xr, yr, zr, &x2, &y2, &z2);-+

            graph(y2, z2, &plotted); ---+

        }                            3차원 곡선을

        plotted = false;      yz평면에 투영한 정사영을 화면에 그림

    }              |

                   +-새로운 곡선을 그림

    getch();

    closegraph(); ---- 그래픽 시스템을 종료

}



/* Rotation order :  z axis -> y axis -> x axis */



void rotate3d(double xr, double yr, double zr,

              double *px, double *py, double *pz)

{

    double x = *px, y = *py, z = *pz;

    double x1, y1, z1, x2, y2, z2, x3, y3, z3;



    x1 = x * cos(zr) - y * sin(zr);   -+

    y1 = x * sin(zr) + y * cos(zr);    | z축을 중심으로 zr만큼 회전

    z1 = z;                           -+



    x2 = x1 * cos(yr) - z1 * sin(yr); -+

    y2 = y1;                           | y축을 중심으로 yr만큼 회전

    z2 = x1 * sin(yr) + z1 * cos(yr); -+



    x3 = x2;                          -+

    y3 = y2 * cos(xr) - z2 * sin(xr);  | x축을 중심으로 xr만큼 회전

    z3 = y2 * sin(xr) + z2 * cos(xr); -+



    *px = x3; -+

    *py = y3;  | 실매개변수 x2, y2, z2에 값을 대입

    *pz = z3; -+ (actual parameter)

}



void graph(double y, double z, int *plotted)

{

    int xx, yy, xasp, yasp;



    getaspectratio(&xasp, &yasp); ---- 화면의 종횡비를 구함

    xx = getmaxx() / 2 + (int)y;

    yy = getmaxy() / 2 - (int)(z * xasp / yasp);

    if (*plotted == false) moveto(xx, yy); --- CP만 이동

    else lineto(xx, yy); ---- 곡선의 시작이 아니면 선을 그림

    *plotted = true;

}

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



<제1회 끝>


다음 글로 계속 이어집니다.
turbo28 터보이빨 임 인 건

계속하시겠습니까? (Y/n) >>


What is Inno Setup?

Posted by Programmer™
2009. 10. 17. 20:57 카테고리 없음
Inno Setup 는 윈도우용 무료 인스톨러이다. 1997년에 처음 선보인후,
오늘날 여러가지 특성과 안정성으로 많은 상업용 인스톨러를 능가하고 있다.

핵심 특성:
  • 오늘날 사용되는 모든 윈도우 버전을 지원한다.: 7, 2008 R2, Vista, XP, 2008, 2003, 2000, Me, 98, 95, and NT 4.0. 
  • 64비트 버전 윈도우용 프로그램 설치에 대한 폭넓은 지원. x64 와 Itanium 아키텍쳐 둘다 지원된다. (On the Itanium architecture, Service Pack 1 or later is required on Windows Server 2003 to install in 64-bit mode.)
  • Supports creation of a single EXE to install your program for easy online distribution. Disk spanning is also supported.
  • 표준 Windows 2000/XP 스타일 마법사 인터페이스.
  • setup 의 타입을 선택할수 있다, e.g. Full, Minimal, Custom.
  • 완벽한 프로그램 삭제 기능.
  • Installation of files:
    Includes integrated support for "deflate", bzip2, and 7-Zip LZMA file compression. The installer has the ability to compare file version info, replace in-use files, use shared file counting, register DLL/OCX's and type libraries, and install fonts.
  • 시작메뉴와 바탕화면을 포함하여 어떤 곳이라도 바로가기를 생성.
  • 레지스트리와 .INI 엔트리의 생성.
  • install 중이나 전후에 다른 프로그램을 실행할수 있다.
  • 다중언어 설치를 지원한다.
  • 패스워드와 암호화된 설치 지원.
  • 디지탈서명된 설치와 삭제를 지원한다..
  • Silent install and silent uninstall.
  • 유니코드 설치. (Windows 2000/XP or later)
  • Integrated Pascal scripting engine option for advanced run-time install and uninstall customization.
  • 전체소스코드를 이용할수 있다.(Borland Delphi 2.0-5.0 and 2009).


상업용으로도 정말 공짜인가?

그렇다, 상업용 응용프로그램을 배포할때 조차도 공짜로 사용할수 있다.

(Note: "Completely free of charge" 를  "completely free"로 착각해서는 안된다. Inno Setup 은 public domain 소프트웨어가 아니라 저작권을 갖는 소프트웨어이다. There are 배포와 사용에는 몇가지 제약이 있다; 자세한 내용은 LICENSE.TXT 파일을 읽어보거라)


Windows XP 블루스크린 발생시 정보수집방법

Posted by Programmer™
2008. 11. 11. 17:17 Windows XP


내컴퓨터 -> 속성 -> 고급을 누르면 아래 화면이 나옵니다.

 

시작 및 복구 -> 설정을 누르면 아래 화면이 됩니다. 
 

 
 
"자동으로 다시 시작"은 체크 안함
작은 덤프 디렉터리 -> 블루스크린 발생시 자동으로 생깁니다.(가끔 생기지 않는 경우도 있음)
그 안에 화일들이 생깁니다. 그 화일을 첨부하여 주시면 에러의 원인규명이 용이해집니다.
 
이 옵션을 사용하지 않으실 경우에는 블루스크린 발생시 디카등으로 촬영하면 됩니다.
(디카가 없으시면 에러코드(0X0000000 등)을 적어서 올려주시면 되겠습니다.