2009년 9월 9일 수요일

중앙대 새로운 중앙도서관 야경



 

 

허접한 야경사진 몇장 올려봅니다 .. 중도의 포스가 느껴지는..

 

 

 



 

 

중앙도서관 우측면 방향에서 ..

주변까지 환해지는.. 말 그대로 빛의 상자군요.

 

 

 



 

 

중앙도서관 좌측면의 모습 .. 주변까지 환하게 !

 

 



 

 

해방광장쪽에서 바라본 중도 우측면 모습 .. 역시 멋진 중도입니다.

 

..

 

 

..

 

 

..

 

 

..

 

 

 


 

 

이건 낮의 중앙도서관 모습 ..

 

 

..

 

..

 

..

 

 

 

 

 

 

 

 

이상 허접한 야경촬영 이었습니다 ..

9시 이후엔 중간층 불이 다 꺼져서.. 며칠 시행착오 끝에 결국 담아냈습니다.

 

..

 

야경촬영은 특히 젬병이라.. 헛점 많아도 그냥 즐겁게 감상해 주시길 ..ㅠㅠ

 

 

 

 

사진에 밴딩 노이즈가 너무 많... 털썩..

노이즈가 너무 많이 보인다면 보시는 분 모니터가 좀 밝게 되어있는 것이니 참고를..

..

 

 

PS 법학관에서 바라본 버드뷰 형식의 야경은 별로 이쁘질 않군요 ,,,

나중에 다시 촬영하던가 해야겠습니다.

다육이 적게 죽이고 키우는 방법


오늘 아이들 약 쳐주고 비 오면 호스로 샤워시킬려고 기다리는 중이네요~

아무래도 비는 오지 않을거 같고...할수 없이 한밤에 영양제 섞은 물만 줘야겠어요~

 

다육이를 알고부터 이번 여름까지 4번의 여름을 보냈네요~

 

첫해에는 멋모르고 푸르게푸르게 키웠다가 겨울에 대거 보내고,

(물 많이 먹고 웃자란 줄기는 쉽게 내려 앉아요)

 

두번째해는 무조건 물을 아끼다가 절반은 깍지로 보내고,

절반은 말려서 보내고

(너무 건조하면 깍지가 기승을 부리고, 장마철에도 물은 줘야해요)

 

세번째해는 장마비 다 맞혀서 세덤과 바위솔 대량 보내고,

다육이들은 뚱뚱이들을 다 만들어서 가을모습이 별로였어요.

(세덤류는 여름장마비가 쥐약이에요~

그리고 비를 너무 맞힌 다육이는 단풍이 덜 들어주네요)

 

네번째 여름인 올해는....

방제를 게을리 했더니 물러서 간아이들이 더러 됩니다.

 

아래 프리린제와 같이 왔던 문버스트와 미니고사옹이 어이없이 갔네요...ㅜㅜ

 



다육이를 키우면서 한아이도 보내지 않고 키우려면

다육이의 노예가 되어야 합니다.

 

취미생활로 기쁨을 얻고자 다육이를 키우는 것인데...

다육이의 노예가 된다면 취지에 어긋나겠지요?ㅎㅎㅎ

 

그래서 이제부터 덜 피곤해 하면서,

그래도 다육이를 적게 죽이는 방법 제가 아는한 공유해 볼까 해요~

 

[제가 즐겨 사용하는 보조제]

살충제 - 코니도(진딧물), 파발마(응애), 매머드(깍지벌레)

(수프라사이드는 고독성이라 사용하지 않아요)

살균제 - 다이센-M, 동부베노밀

 

주의사항 :

대부분 1000배희석이므로 정확한 비율로 희석하는게 젤로 중요합니다.

벌레가 지긋지긋하다고 강하게 희석하면 다육이를 잡을수 있습니다.

그게 무서워 너무 약하게 희석을 할 경우 원하는 살충과 살균효과는 얻지 못하고 벌레들에게 내성을 길러줄 수 있답니다.

전 2ml 계량해서 2리터 생수병에 희석해서 한번씩 쫙 뿌려주고 다시 쫙 뿌려주고 모두 사용하면서 흠뻑 적셔줍니다.

혼용해서 사용하는건 굉장한 주의와 모험이 필요하므로 단독으로 번갈아 사용합니다.

 

여기서 잠깐,

약제 살포는 반드시 바람이 없는 날이나 바람이 몸쪽으로 오지 않는날 뿌려주세요~

그리고 전 3~4시간후에는 반드시 샤워를 시켜줍니다.

약한 아이들은 약해 때문에 죽을수가 있어서 샤워 시킨후 통풍이 잘 되게 해줘야 해요~

약치고 물준뒤 통풍시켜주지 않는건...약치지 않으니만 못하답니당~~

 

 

제가 사용하는 시기를 적어볼게요~ ^^

 

 

1. 다육이를 집으로 들인날 분갈이후 >> 중요!!

살균제(다이센엠)을 살포한 후 3시간후 샤워시키고 베란다안 바람 잘드는곳에서 안정시킨다.

 

이유는?

농원에서는 여러곳에서 모인 다육이들이 있으므로 깍지벌레나 진딧물등 해충이 있을 확률이 높아요~

이쁜 다육이를 들인거지만 벌레도 같이 들였다고 보심 되지요~

만약 그대로 집에 있는 아이와 섞어두신다면....ㄷㄷㄷ

깍지벌레가 느려보여도 바람과 같이 번져나가더라구요...@@

 

그리고 농장에서 속성으로 키운 다육이들은

약해서 집에서 쉽게 무를수 있으니 살균제처리를 해주면 잘 견디더라구요~

 

제가 올여름에 새로온 아이들을 귀찮아 그냥 두었더니 몇몇이 허무하게 가더라구요~

그이전에 부지런하게 작업해 주었을때는 자리도 빨리 잡고 새로 들인아이가 가는일은 없었답니다.

 

요것만 잘해도 건강하게 아이들 키울수 있어요~ ^^

 

 

2. 봄과 가을철 다육식물관리

봄과 가을은 다육이들이 젤로 좋아하는 성장시기인걸 아시잖아요~

그냥 두어도 잘 자라겠지만....

살짜기 도와주면 아이들이 정말 좋아해요~ ^^

 

전 보름, 안되면 한달에 한번씩 꼭 액체비료를 1000배희석해서 흙쪽으로 흠뻑 준답니다.

너무 도와주신다고 진하게 희석하시면 절대 안되세요~

과유불급~아시져!!

 

시간대는 저녁에서 밤사이~

그래야 물이 대략 말라서 한낮에 햇살에 익는걸 방지할 수 있답니다.

아침에 주시면 자칫 다육이숙회가 될 수 있어요...ㅜㅜ

 

영양제를 주시면

첫째, 면역력이 강해져서 벌레가 덜 생깁니다.

둘째, 잎과 줄기가 단단하게 자라서 겨울과 여름을 잘 견딥니다.(과하면 역효과)

세째, 물을 좀 말려도 통통한 잎장을 유지해 줍니다.

넷째, 분갈이를 안해줘도 되요..ㅎㅎㅎ

 

단점이라면....가을에 단풍이 좀 덜 올라와요~~^^;;

 

그리고 봄에는 여름대비 살균제 횟수를 더 많이,

가을에는 겨울대비 살충제 횟수를 더 많이해서 방제도 꼭 잊지말고 해주세요~ ^^

 

 

아래 크라우스 울집에 온지 2년 넘었는데 분갈이 한번도 안해줬어요~

 



  

3. 여름철 다육식물관리

젤로 어려운게 여름이죠~

지긋지긋해져서 아주 지쳐 나가떨어질때쯤에 그나마 가을이 와주니 다행이라 해야겠지요~ㅎㅎㅎ

 

첫째, 장마대비 비가림은 꼭 해줘야 하는데요~

특히 여름(6월초순부터 7월중순) 장마때 며칠연속 비가 내릴때는 반드시 비가림을 해줘야 해요~

 

둘째, 장마가 끝난후 7월말부터 8월말까지는 폭염 때문에 빛가림을 해줘야 합니다.

그리고 이때는 자칫 물 잘못 주거나 비 맞고 바로 해나면 통통한 다육이들 삶아져서...먹을수도 엄꼬..ㅜㅜ

화분이 젖었는데 해가 나면 그늘을 만들어 주거나,

선풍기를 틀어서라도 화분을 말려주세요~

정 불안하면 많이 젖은아이들은 베란다안으로 들이시는게 웃자라더라도 살리는 길이에요~

 

유의할점은 장마철이라 해서 무조건 물을 안주는건 무리구요~

너무 쪼글거리는 아이들은 되도록 밤에 물을 주심 되세요~

 

참, 여름에 영양제는 절대 주심 안되세요~^^

 

아래 명월이는 2006년도 살던 화분에 그대로 살기에...

장마때도 저보러 물달라 하는 아이네요~ ^^;;

 





4. 겨울철 다육식물관리

겨울은 의외로 수월한 계절입니다.

냉해만 입지 않게 해주시고 동형종 아이들만 신경써주면 되는계절이라~

다육맘들에겐 휴식과 같은 계절이죠~ ^^

 

첫째, 10월말전에는 베란다안으로 들여서 냉해 입지 않게 해야해요~

추위에 강한 아이도 있지만...대체적으로 영상5도이하는 위험한거 같아요~

 

둘째, 베란다 안에 들일때 가능하면 해드는 방향을 체크해서 최대한 빛을 많이 볼 수 있게 해주세요~

바닥과 벽에 알미늄호일을 깔아서 빛반사를 도와주시는 방법도 있어요~

 

세째, 베란다안에 온도계를 설치하시고 강추위가 올경우에는 특히 창가쪽 냉기를 막아주시고,

밤에는 신문지를 덮어서 냉해를 막아주세요~

 

넷째, 겨울에는 건조하면 깍지가 잘 생기니 볕좋은 한낮에 깍지벌레약을 가끔 살포해 주세요~

물은 한달에 한번쯤 온도가 높은날 오전중에 위만 젖을정도로 살짝씩 주셔야 해요~

 

이렇게 관리를 하시다가 삼월삼짇날이 지나 한낮에 온도가 높은날은

가끔 베란다문을 열어서 직광훈련을 시켜주세요~(추운날 냉해 조심)

그리고 식목일이 지나서 (그전에는 아무리 따뜻해도 냉해의 위험이 있더라구요)

비가 온 후에 다육이들을 밖으로 내 보내시면 화상의 위험이 적답니다.

 

아래 립스틱이 올 봄에 직광훈련없이 쨍한날 겁없이 내어놓았다가 화상 입은 아이랍니다.

한번 입은 화상은 일년이 지나야 잎이 떨어져 나가니까 내내 속 쓰려요~ ^^;;

 



 

이상 제가 아는한 다육이 최대한 적게 죽이는 방법이었습니다.

주절주절 말이 많았는데...

뻔한얘기, 얕은얘기, 맞지 않는 이야기일수도 있어요~

그래도 조금이라도 도움 되셨으면 하는 마음에 적어보았답니다.

 

저보다 고수분들이 워낙 많으셔서.... 쑥스럽네요~ㅎㅎ

지적은 언제든 감사합니다~~ ^^

 

윈도우 환경에서 시간측정하는법 - 초정밀 카운터

글은 마이크로소프트웨어 99 2월의 "이보다 더 정확할 순 없다! 윈도우 환경에서 시간측정하는법" 이란 기사에서 참고한 것입니다. ( 저작권 걸리나요? )

 

윈도우 상에서 시간을 측정하기 위한 방법에는 몇가지가 있는데, clock() 함수를 사용하거나 WM_TIMER 메시지를 사용한다거나, 일반 타이머보다 더 높은 정확도를 위해 멀티미디어 타이머를 사용할 수 있다.

WM_TIMER의 경우는 초당 클럭수가 18.3 이므로 1/18.3 , 55 ms 정도의 정확도를 가진다. 그리고 멀티미디어 타이머의 경우는 최소시간 간격이 1ms 이고, 10ms 이내의 이벤트 지연시간을 가지는 타이머 이벤트는 CPU 자원을 많이 소모하기 때문에 주의해야 한다.

앞서 설명한 멀티미디어 타이머는 최소 시간간격이 1ms, 그 이하의 시간을 측정하는데는 적합하지 않다. 더구나 CPU의 성능이 높아지면서 1ms는 무척 긴 시간이 돼 버렸다. 1ms 동안 많은 명령을 수행할 수 있기 때문에 네트웍 패킷의 전송시간이나 특정 루틴의 시간을 측정하기 위해서는 멀티미디어 타이머는 도움이 되지 않는다. 이러한 경우에 Win32 API에서 제공하는 QueryPerformanceFrequency QueryPerformanceCounter , 이 두 개의 함수가 유용하게 쓰인다.

 QueryPerformanceFrequency 1초 동안 카운터가 증가하는 값을 얻어내는데, 시스템이 이 두 함수들을 지원하지 않으면 QueryPerformanceFrequency 의 값이 0 이 되고 결과값도 0 이 돌아온다.

다음 코드는 VC++에서 카운터를 사용한 예이다.

//-----------------------------------------------------------

#include "stdafx.h"  // pre-compiled header file for VC++

#include "windows.h"

#include "stdio.h"

 

void main()

{

        LARGE_INTEGER freq, start, end;

        LARGE_INTEGER tmp;

 

        if(QueryPerformanceFrequency(&freq)) {

                QueryPerformanceCounter(&start);

                printf("Performance Frequency is %I64d\n", freq);

                QueryPerformanceCounter(&end);

                printf("Performance Resolution is %4.3f micro sec.\n",

                        1.0/freq.QuadPart * 1000000);

                printf("printf elapsed time is %4.3f micro sec.\n",

                        (double)(end.QuadPart-start.QuadPart)/freq.QuadPart*1000000);

 

                QueryPerformanceCounter(&start);

                        QueryPerformanceCounter(&tmp); // 1

                        QueryPerformanceCounter(&tmp); // 2

                        QueryPerformanceCounter(&tmp); // 3

                        QueryPerformanceCounter(&tmp); // 4

                        QueryPerformanceCounter(&tmp); // 5

                        QueryPerformanceCounter(&tmp); // 6

                        QueryPerformanceCounter(&tmp); // 7

                        QueryPerformanceCounter(&tmp); // 8

                        QueryPerformanceCounter(&tmp); // 9

                        QueryPerformanceCounter(&tmp); // 10

                QueryPerformanceCounter(&end);

 

                printf("QueryPerformance delay time is %4.3f micro sec.\n",

                        (double)(end.QuadPart-start.QuadPart)/freq.QuadPart*100000); //  /10

        } else

                printf("This computer don't support QueryPerformance function sets !!\n");

}

//--------------------------------------------------------

 Pentium II-266 , Windows 2000 professional 에서의 결과는 다음과 같다.

Performance Frequency is 3579545

Performance Resolution is 0.279 micro sec.

printf elapsed time is 801.499 micro sec.

QueryPerformance delay time is 3.771 micro sec.

 

위 코드에서 LARGE_INTEGER 에 대한 MSDN의 설명은 다음과 같다.

The LARGE_INTEGER structure is used to represent a 64-bit signed integer value.

typedef union _LARGE_INTEGER {

    struct {

        DWORD LowPart;

        LONG  HighPart;

    };

    LONGLONG QuadPart;

} LARGE_INTEGER;

 

Members

LowPart

Specifies the low-order 32 bits.

HighPart

Specifies the high-order 32 bits.

QuadPart

        Specifies a 64-bit signed integer.

====================================================================

앞에서 설명한 API 보다 좀 더 정확한 방법으로 수행 시간을 측정하기 바란다면 한 가지 방법이 있다. 이 방법은 Win32 API를 이용한 것이 아니라 어셈블리를 이용한 방법으로 인텔 펜티엄 이상에서만 수행시킬 수 있는 방법이다. 펜티엄에서 추가된 명령중에 RDTSC(Read from Time Stamp Counter) 라는 것이 있다. 펜티엄은 내부적으로 TSC(Time Stamp Counter)라는 64비트 카운터를 가지고 있는데, 이 카운터의 값은 클럭 사이클마다 증가한다. RDTSC 명령은 내부 TSC 카운터의 값을 EDX EAX 레지스터에 복사하는 명령이다. 이 명령은 6에서 11 클럭을 소요한다.

다음의 rdtscEx 명령은 36 클럭을 소요하며 측정구간을 클럭단위로 측정할 수 있는 강력한 시간 측정 방법이다. 하지만 이 방법은 클럭 수만 측정할 뿐 시간을 알 수는 없다. 정확한 시간을 알려면 시스템의 CPU 클럭을 알아야 하며 측정한 클럭값을 CPU 클럭으로 나누어야 시간이 나온다.

 RDTSC 명령을 수행할 때 CPU가 수행속도 향상을 위해서 CPU 명령순서가 바뀔 수 있기 때문에 CPUID 명령을 전에 수행해 명령순서를 맞춰야 하는 경우도 있다.

//------------------------------------------------------

#include "stdafx.h"  // pre-compiled header file for VC++

#include <windows.h>

#include <stdio.h>

 

#define rdtsc(x) \

{ __asm __emit 0fh __asm __emit 031h __asm mov x, eax}

#define rdtscEx(low, high) \

{ __asm __emit 0fh __asm __emit 031h __asm mov low, eax _asm mov high, edx}

#define cpuid {__asm __emit 0fh __asm __emit 0a2h}

 

int main(void)

{

    LARGE_INTEGER start, end, tmp;

    __int64 freq, diff;

 

    if (QueryPerformanceFrequency((LARGE_INTEGER*)&freq)) {

        rdtscEx(start.LowPart, start.HighPart);

        printf("Performance Frequency is %I64d\n", freq);

        rdtscEx(end.LowPart, end.HighPart);

        printf("Preformance Resolution is %4.3f micro sec.\n",

                        1.0/freq * 1000000);

        diff = *(__int64*)&end - *(__int64*)&start;

        printf("printf elapsed clock cycle is %I64d\n", diff);

        printf("printf elapsed time is %4.3f micro sec.\n",

                        (double)diff/266);  // 클럭에 따라 이 부분이 바뀌어야한다.

 

        rdtscEx(start.LowPart, start.HighPart);

                rdtscEx(tmp.LowPart, tmp.HighPart); // 1

                rdtscEx(tmp.LowPart, tmp.HighPart);

                rdtscEx(tmp.LowPart, tmp.HighPart);

                rdtscEx(tmp.LowPart, tmp.HighPart);

                rdtscEx(tmp.LowPart, tmp.HighPart);

                rdtscEx(tmp.LowPart, tmp.HighPart);

                rdtscEx(tmp.LowPart, tmp.HighPart);

                rdtscEx(tmp.LowPart, tmp.HighPart);

                rdtscEx(tmp.LowPart, tmp.HighPart);

                rdtscEx(tmp.LowPart, tmp.HighPart); // 10

        rdtscEx(end.LowPart, end.HighPart);

        printf("rdtscEx elapsed clock clycle is %I64d\n",

                        (*(__int64*)&end - *(__int64*)&start)/10);

    } else

        printf("This computer don't support QueryPerformance function sets!!\n");

}

//----------------------------------------------------

결과는 다음과 같다.

Performance Frequency is 3579545

Preformance Resolution is 0.279 micro sec.

printf elapsed clock cycle is 182771

printf elapsed time is 687.109 micro sec.

rdtscEx elapsed clock clycle is 36

 

지금까지 측정한 시간들은 절대적인 값이라 볼 수는 없다. 실제로 위에서 소개한 두 코드를 가지고 여러번 실행해 보면 그때마다 값이 조금씩 다르게 나오는 것을 볼 수 있는데 그건 윈도우가 멀티 태스킹 환경이기 때문에 다른 영향을 받을 수 있기 때문이다. 그리고 windows 98 windows 2000 에서도 값이 다르게 나올 거라 생각한다. (직접 해보진 못했지만..)

그냥 상대적인 비교만으로 족할 듯 하다..

- the end of this article -

2009년 9월 2일 수요일

리뉴얼 완료~!! 중앙대학교 중앙도서관

2009년 9월 1일 새학기의 시작과 함께 중앙대학교의 도서관이 리뉴얼을 끝내고 개관식을 치렀다.

 

기존 도서관의 역사성을 유지하며 활용도를 극대화 시키는데 역점을 뒀다고 하던데......

 

처음 둘러본 소감은 역시나!!!였다.

 

아래 사진을 통해 둘러보자. 출처는 중앙인에서 피메님이 올려주신 사진과 글들을 그대로 활용... ^^

 


 

 

커튼월 이라고 하던데.... 벽면 전체가 유리로 이루어져 있어서 채광효과는 확실히 좋은듯...

낮에는 빛을 끌어 들이고, 밤에는 반대로 빛을 뿜어내는....

빛의 상자라고나 할까?

 

 

 

지나치게 빛이 들어오지 않게 적절히 조절해주는 기능이 있어 보이더군요.

게다가 도서관 외부는 반사되는 빛으로 주변까지 환해지는 느낌이..^^*

(새건물이라서 그런건지...기분까지 삐까번쩍..ㄷㄷㄷ)

 


 

 

중앙도서관 1층 로비에 들어오는 저 빛 보이시죠? 따스한 햇빛이 지나치지 않으면서 적당한 밝기로 스며드는데,

정말 느낌이 좋았답니다.  그 느낌이 사진을 보시는 분에게 잘 전해질지 모르겠지만......

 

 

 


 

열람실 내부 (특히 4층 열람실들) 까지 스며드는 적절한 밝기또한, 정말 느낌이 좋았습니다.

 

 

 

 


 

중앙대학교 학우들의 일상 -  

좋은 날씨 속, 아름다운 중앙도서관 옆길입니다.

 

 

 


 

채광에도 도움되고 경관도 아름다운 중정(중앙정원) 입니다.

 

 

 


 

중앙정원 위가 이렇게 탁 트여 있어서, 빛이 1층에서 4층까지 골고루 퍼지도록 설계되었군요 ..

 

..

 

 

..

 

 

..

 

 

..

 

 

..

 

 

 

 

 

간단하게 채광 측면에서 살펴본 .. 허접한 탐방기였습니다.

 

모든사진은 긴축 1280px로 맞춰져 있습니다.

2009년 9월 1일 화요일

전처리문의 종류(#include, #define, #ifdef, ... )

전처리문의 종류(#include, #define, #ifdef, ... )

 

전처리문이란?

실질적인 컴파일 이전에 미리 처리되는 문장을 가리킨다. 선행처리기라고도 한다. 따라서 컴파일러는 사용자가 작성한 코드를 컴파일하기 전에 전처리문에서 정의해 놓은 작업들을 먼저 수행한다.

종류로는 #define, #if, #ifdef, #ifndef, #defined, #undef 등이 있다. 이것은 기존에 있는 방대한 소스 코드를 지우지 않고 활성화 비활성화 하는 데에 가장 많이 이용된다. 즉, 기존에 있는 소스 코드를 건드리지 않는 상태에서 부분적인 컴파일을 하는 것이다.

C의 전처리문이 오는 줄(Line)의 첫 문자는 항상 '#'으로 시작한다. ANSI 표준에 따른 C의 전처리문의 종류가 아래에 나와 있다.

 

- 파일 처리를 위한 전처리문 : #include

- 형태 정의를 위한 전처리문 : #define, #undef

- 조건 처리를 위한 전처리문 : #if, #ifdef, #ifndef, #else, #elif, #endif

- 에러 처리를 위한 전처리문 : #error

- 디버깅을 위한 전처리문 : #line

- 컴파일 옵션 처리를 위한 전처리문 : #pragma 

 

조건 처리를 위한 전처리문은 어떤 조건에 대한 검사를 하고 그 결과를 참(0 이 아닌 값) 또는 거짓(0)으로 돌려준다.

#if : ...이 참이라면

#ifdef : ...이 정의되어 있다면

#else : #if나 #ifdef에 대응된다.

#elif : "else + if"의 의미

#endif : #if, #ifdef, #infdef 이 끝났음을 알린다.

 

이하 각 전처리문의 상세를 설명한다.

 

#include

헤더 파일과 같은 외부 파일을 읽어서 포함시키고자 할 때 사용된다. 이때의 파일은 이진파일(Binary file)이 아닌 C의 소스파일과 같은 형태의 일반 문서파일을 말한다.

 

    #include <stdio.h>        /* 이 위치에 stdio.h라는 파일을 포함시킨다. */

    #include "text.h"           /* 이 위치에 text.h라는 파일을 포함시킨다. */

 

'<...>'를 사용할 때와 '"..."'를 사용할 때의 차이점은 '<...>'는 컴파일러의 표준 포함 파일 디렉토리(또는 사용자가 별도로 지정해 준)에서 파일을 찾는 것을 기본으로 한다.  그리고 "..."'를 사용했을 때는 현재의 디렉토리를 기본으로 파일을 찾게 된다. 아예 디렉토리를 같이 지정할 수도 있다.

 

    #include <C:\MYDIR\MYHEAD.H>

    #include "C:\MYDIR\MYHEAD.H"

 

#define

상수값을 지정하기 위한 예약어로 매크로라고 부른다. 구문의 상수로 치환한다.

또한 #define은 함수 역활과 비슷하게 아래와 같이 쓰일 수 있다.

#define SUM(x) ((x) = (x) + (x))

동작원리는 함수와 같다. 말 그대로 main소스에서 SUM을 호출하면 옆에 있는 더하기 코드가 치환되는 것이다.

 

#define으로 정의할 수 있는 것은 숫자만이 아니다.

#define MYNAME "Young Hee"

printf(MYNAME);

라고 한다면 이는 전처리기에 의해

printf("Young Hee");와 같이 전개되는 것이다.

 

이렇게 #define으로 정의된 것은 일반적인 변수와는 다르다. 그 차이는 명백한데, 예를 들어서

#define MYNAME "Turbo"

char my_name[] = "Turbo"

의 두가지 경우가 있다고 하자. "MYNAME"은 전처리문으로 "my_name"은 문자형 배열 변수로 정의되었다.

printf(MYNAME);

printf(MYNAME);

printf(my_name);

printf(my_name);

이것을 전처리한 상태는 다음과 같이 될 것이다.

printf("Turbo");

printf("Turbo");

printf(my_name);

printf(my_name);

이런 결과에서 우리가 유추해 볼 수 있는 것은 전처리 명령을 사용했을 경우 "Turbo"라는 동일한 동작에 대해서 두개의 똑같은 문자열이 사용됐고, 변수를 사용했을 경우에는 하나의 문자열을 가지고 두번을 사용하고 있다는 것이다. 결과적으로 이런 경우에는 전처리문을 사용했을 경우 메모리 낭비를 가져 온다는 것을 알 수 있다.

 

#undef

#define으로 이미 정의된 매크로를 무효화한다.

#define ADD(a, b) (a + b)

#undef ADD(a, b)

라고 하면 앞으로 사용되는 ADD(...)는 'undefined symbol'이 되어 에러 처리 된다.

 

#if ~ #endif

#if 구문은 if랑 아주 비슷하다. 이것은 어떠한 구문을 컴파일 할지 안할지를 지정할 수 있다.
#define A 1
#if A
    source code.....
#endif
위 source code 부분은 컴파일이 된다. if문에서와 같이 참, 거짓을 구분하여 컴파일이 된다. 위에서 A값은 1 즉 0보다 큰 수이기 때문에 참인 것이다.

직접 아래와 같이 하면 거짓이기 때문에 source code 부분은 컴파일이 되지 않는다.

#if 0

    source code....

#endif

 

#ifdef ~ #endif
컴파일 할 때

#define MYDEF               /* MYDEF는 값은 가지지 않았지만 어쨋든 정의는 되었다 */

#ifdef YOURDEF              /* 만약 YOURDEF가 정의되어 있다면... */

    #define BASE 10         /* BASE == 10 */

#elif MYDEF                 /* 그외에 MYDEF가 정의되었다면... */

    #define BASE 2       /* BASE == 2 */

#endif
와 같이 쓰면 BASE는 상수 2로 치환되어
전처리기가 컴파일러에게 넘겨준다.

#ifndef 헤더명_H__ ~ #endif

헤더파일이 겹치는 것을 막기 위한 일종의 매크로이다. 예를 들어 헤더파일에 어떤 클래스의 인터페이스 선언을 넣었다고 하자. 이 클래스 인터페이스에서 다른 파일의 프로토타입이 필요해서 다른 A 파일을 include 하고 있는데 이 헤더 파일을 include 하는 파일에서 A라는 헤더 파일을 이미 include 하고 있다면 두번 define한 것이 된다. 그러면 SYNTEX 에러가 난다. 그래서 그런 것을 막는 방법의 하나로 #ifndef을 사용한다. 이전에 include되어 있으면 #endif쪽으로 점프해버려 결국 한번 선언되는 것이다.

#include  <stdio.h>    ------ (a)

#include  <stdio.h>    ------ (b)
이러허게 두번 썼다고 하자. 그런데 앞에 이미 include를 했는데 밑에 또 한다면 문제가 된다. 컴파일러가 검사해야할 코드량도 많아진다. 그래서 stdio.h에는

#ifndef STDIO_H__

#define STDIO_H__

가 선언되어 있다. 만약 STDIO_H가 선언되어 있지 않다면 선언한다는 뜻이다. 그 뒤 (b)에서는 이미 (a)쪽에서 STDIO_H__ 을 선언한 상태이기 때문에 전처리기 쪽에서 무시해버린다. 그러므로 컴파일러는 (a)만 검사한다.

 

#defined

define이 여러 개 되어 있는지를 검사할 때 쓴다. 이것은 여러 개를 동시에 검사 할 수 있다.

#if #defined A || #defined B

 

#ifdef와 #if defined의 차이

#ifdef는 정의가 되어 있는지를 테스트 하기 때문에, 한번에 여러 개를 사용할 수 없다. 형식이

#ifdef name

처럼, 하나의 토큰이 되어야 하기 때문이다.

 

여러 개가 정의되어 있는지를 테스트 하기 위해서는

#if defined(MACRO1) || defined(MACRO2)

처럼 사용한다.

#if는 ||로 중첩해서 사용할 수 있다. 형식이, #if expression이므로, C 표현이 올 수 있다.

#if MACRO1 || MACRO2

처럼 사용해도 된다.

 

#error

소스 라인에 직접 에러 메세지를 출력한다. 전처리기가 #error 문을 만나면 그 즉시 컴파일을 중단하고 다음과 같은 에러 메시지를 출력한다.

ERROR : XXXXX.c ########: Error directive: 내용

    - XXXXX.c --> 현재 컴파일 중인 파일명

    - ####### --> 전처리기가 #error 문을 만난 시점에서의 행 번호(헤더 포함)

 

#ifdef __LARGE__

#error This program must be compiled in LARGE memory model!

#endif

이 내용은 만일 프로그램이 LARGE 모델이 아니라면 "#error" 뒤에 표시된 메세지를 출력하고 컴파일을 중지하게 된다.

 

#line

이 명령은 소스 코드의 행번호를 지정하기 위한 것으로 주로 컴파일러에 의해 미리 정의된 __LINE__과 함께 사용된다. C에서는 베이식과 같은 행번호를 사용하지 않는다. 하지만 디버깅을 하다 보면 "행번호를 알 수 있으면 좋을텐데"하는 경우가 있다. 예를 들자면 어떤 표현들이 있고, 그 표현들 중의 어딘가에 잘못된 부분이 있는 것 같은데 정확히 그 표현이 있는 행을 찾지 못한다면 "#line"을 사용함으로써 그 일을 보다 수월하게 할 수 있게 된다.

__LINE__과 __FILE__을 각각 행번호와 파일명으로 변경한다.

#include <stdio.h>

 

#define DEBUG

 

void main(void)

{

    int count = 100;

 

    #line 100               /* 다음 줄번호를 100으로 설정한다 */

                               /* <-- 이 줄의 번호가 100이다 */

    #ifdef DEBUG        /* <-- 이 줄의 번호가 101이다 */

    printf("line:%d, count = %d\n", __LINE__, count);

    #endif

 

    count = count * count - 56;

    #ifdef DEBUG

    printf("line:%d, count = %d\n", __LINE__, count);

    #endif

 

    count = count / 2 + 48;

    #ifdef DEBUG

    printf("line:%d, count = %d\n", __LINE__, count);

    #endif

}

#pragma

컴파일 옵션의 지정. 컴파일러 작성자에 의해서 정의된 다양한 명령을 컴파일러에게 제공하기 위해서 사용되는 지시어이다. 컴파일러의 여러가지 옵션을 명령행 상에서가 아닌 코드상에서 직접 설정한다.  #pragma는 함수의 바로 앞에 오며, 그 함수에만 영향을 준다. Turbo C는 9개의 #pragma문(warn, inline, saveregs, exit, argsused, hdrfile, hdrstop, option, startup)을 지원하고 있다.

 

#pragma inline : 컴파일할 때 어셈블러를 통해서 하도록 지시한다.즉, 인라인 어셈블리 코드가 프로그램에 있음을 알려준다. (명령행 상에서 '-B' 옵션)

#pragma saveregs : 이 홉션은 휴즈 메모리 모델에 대해 컴파일된 함수에게 모든 레지스터를 저장하도록 한다.

#pragma warn : 이 지시어는 Turbo C에게 경고 메시지 옵션을 무시하도록 한다.

 

#pragma warn -par

이는 매개 변수(parAMETER)가 사용되지 않았다고 경고(warnING)를 내지 못하도록 한다. 이와 반대되는 표현은

#pragma warn +par

이다.

경고의 내용 앞에 (+)를 사용하면 경고를 낼 수 있도록 설정하고, (-)를 사용하면 경고를 내지 못하도록 하는 것은 모든 경고에 대해 동일하다. 명령행에서는 "-wxxx"로 경고를 설정하고 "-w-xxx"로 경고를 해제한다. 경고의 종류는 무척 많은데 자주 사용되는 것을 아래에 나타냈다. 모든 것을 알고 싶다면 컴파일러 User's Guide의 명령행 컴파일러 부분을 참고하시기 바란다.

 

par : 전해진 파라미터가 사용되지 않음

rvl : void 형이 아닌 함수에서 리턴값이 없음

aus : 변수에 값을 할당했으나 사용하지 않았음

voi : void 형 함수에서 리턴값이 사용되었음

sig : 부호비트(MSB)가 고려되지 않은 형변환(type-castion)에서 부호 비트를 소실할 수 있음

 

C의 predefined macro

__FILE__ a string that holds the path/name of the compiled file
__LINE__ an integer that holds the number of the current line number
__DATE__ a string that holds the current system date
__TIME__ a string that holds the current system time
__STDC__ defined as the value '1' if the compiler conforms with the ANSI C standard
__cplusplus determines if your compiler is in C or C++ mode. Usually used in headers

 

예)

#include <stdio.h>  

void main(void) 

    printf("The path/name of this file is %s\n", __FILE__); 
    printf("The current line is %d\n", __LINE__); 
    printf("The current system date is %s\n", __DATE__); 
    printf("The current system time is %s\n", __TIME__);  

    #ifdef __STDC__ 
        printf("The compiler conforms with the ANSI C standard\n"); 
    #else 
        printf("The compiler doesn't conform with the ANSI C standard\n"); 
    #endif 
    #ifdef __cplusplus 
        printf("The compiler is working with C++\n"); 
    #else 
        printf("The compiler is working with C\n"); 
    #endif 

 

  프로그래머들 마다 코딩 스타일(암시적 약속)이 있다. 보통 매크로, const 변수는 대문자로 적는 것이 원칙이다. 매크로 함수와 일반함수, 매크로 대상체(object-like macro)와 일반 변수를 구분하기 쉽게 해주는 것이기 때문이다.

#define STDIO_H_

왜 뒤에 _를 붙였을까? 이것도 하나의 암시적 약속이다. 컴파일러 제작회사는 매크로를 정의할 때 사용자들과 이름이 충돌이 나지 않게 하기 위해서 대부분 _를 뒤어 덧붙인다. 또한 _를 하나 혹은 두 개 연속으로 시작하는 것은 컴파일러 내부에서 사용하는 매크로라는 성격이 강하다. 물론 강제적인 뜻은 없으며 단지 관습상 그렇다. 왜 이것이 관습이 되었나 하면 보통 매크로 변수 이름이나 함수 이름을 지을 때 뒤에 _를 붙이지 않기 때문이다. 그래서 함수 제작자들이 _를 단골로 붙였다.