S/W 개발/Embarcadero2007.12.06 10:37
간단하지만.. 자주 까먹는 관계로 정리..
VCL에서 날짜는 상수부분에서 처리
시간은 소수점 이하 지수부에서 처리..
시간 날짜 동시에 처리할 경우에는 double이나..TDateTime 변수 사용..

///////////////. hpp ///////////////////////////////////////
#include "time.h"

// 변수 정의
 TTime  tMin;    // 경과시간
 TTime  tEnd;    // 마지막 정지 시간
 TTime  tNow;   // 현재 사용 시간 
 TTime  tPost;   // 사용 시간 임시 저장용..  
 TTime  tStart;   // 사용 시간 임시 저장용..

 TTime d_time ;

// TTime 은 시간만 처리시(소수점 이하만 구함)
// TDate 는 날짜만 처리히(상수부만 처리)
// TDateTime 는 상수와 지수부분 모두 처리.

/////////////// .cpp //////////////////////////////////////

   //변수 기본값 처리..
   tMin = 0;
   tEnd  = Now();   // 날짜와 시간 모두 처리.. 시간만 처리시는 Time(),  날짜만 처리시는 Data()
   tPost = 0;  
   tStart = Now();  

   // 일시 멈춤시 이전값 저장..
    tPost =  tMin;


    // 시간 구하기..
    tNow = Now(); 
    tMin = tNow - tEnd + tPost;

   // 시간 표시.
 d_time = Global->tMin;  
 DecodeTime(d_time, Hour, Min, Sec, MSec);
 lbl_UseTime->Caption = AnsiString().sprintf("작업 시간 : %02d:%02d:%02d", Hour, Min, Sec);
Posted by 가희나희아빠 희자매(가희나희)아빠
TAG 계산, 시간
S/W 개발/Embarcadero2007.12.06 10:36
폼을 기본으로 작성된 클래스라면..

TMyClass MyClass; 

로 생성하면 됨...

VCL 기반이라면...

아래의 방법으로 생성..

TMyClass* pMyClass = new TMyClass();

아래는 볼랜드포럼에서 퍼온 내용...

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


클래스 자체가 꼭 new 로 생성을 해야만 메모리가 할당되는 것은 아닙니다.

class TMyClass
{
    Method1()
    ...
}

으로 만드신 베이스 클래스라면 일반 스트럭처와 동일하게 사용할 수 있습니다.
스트럭처와 클래스는 분명 큰 차이점이 있지만 그 기반은 동일하니까요.

TMyClass MyClass;

MyClass.Method1() 의 형식으로 호출이 가능하며 메모리 누수와는 관계가 없습니다.
그리고 MyClass 는 컴파일 시에 TMyClass 만큼의 메모리가 할당되며 프로그램 종료시에
해제됩니다.

보통 빌더에서 new 를 사용해서 객체를 생성하는 것은 델파이에서 온 VCL Class 때문입니다.
VCL 클래스는 반드시 new 를 통한 메모리 할당을 통해서 이용해야 합니다.
VCL 의 구조적 특성( ^^ 예전에 읽었는데 영문이라 대충 읽어서 ... ) 때문입니다.

만약 클래스를 VCL 클래스 기반으로 만든다면 VCL 베이스 클래스인 TObject 를
상속받으시면 됩니다.

class TMyClass : public TObject
{
    Method1()
    ...
}

TMyClass* pMyClass = new TMyClass();
pMyClass->Method1();

이 되는 것이죠....

'S/W 개발 > Embarcadero' 카테고리의 다른 글

간단한 시간 날짜 계산  (0) 2007.12.06
BCB에서 클래스 참조시 주의사항  (0) 2007.12.06
BDS 단독 실행 프로그램 만들기  (0) 2007.12.06
볼랜드 기본 칼라 Define  (0) 2007.12.06
Posted by 가희나희아빠 희자매(가희나희)아빠
TAG 클래스
S/W 개발/Embarcadero2007.12.06 10:35
6.0 이하 버전 --------------------------
컴파일  전
Project->Options... 메뉴를 선택해서

"Linker" tab 에서, "Linking"이라는 항목에서

"Use dynamic RTL"을 disable
"Packages" tab에서 "Build with runtime packages"을 disable


OCX나 Active X 를 사용시, registry setting

bds 2006 -------------------------------

위의 내용과 동일..

UI변경으로..
페이지컨트롤 대신 트리뷰로 변경 되었음..
  Linker 노드와 Packages 노드에서 찾으면 됨..

'S/W 개발 > Embarcadero' 카테고리의 다른 글

BCB에서 클래스 참조시 주의사항  (0) 2007.12.06
BDS 단독 실행 프로그램 만들기  (0) 2007.12.06
볼랜드 기본 칼라 Define  (0) 2007.12.06
INI 파일  (0) 2007.12.06
Posted by 가희나희아빠 희자매(가희나희)아빠
S/W 개발/Embarcadero2007.12.06 10:34
// Color Define
//////////////////////////////////
#define NONE                 clNone
#define AQUA                  clAqua
#define BLACK                clBlack
#define BLUE                   clBlue
#define CREAM                clCream
#define DARKGRAY           clDkGray
#define FUCHSIA               clFuchsia
#define GRAY                   clGray
#define GREEN                 clGreen
#define LIME                    clLime
#define LIGHTGRAY          clLightGray
#define MAROON             clMaroon
#define MEDIUMGRAY      clMedGray
#define MINTGREEN        clMoneyGreen
#define NAVYBLUE          clNavy
#define OLIVEGREEN       clOlive
#define PURPLE              clPurple
#define RED                    clRed
#define SILVER                clSilver
#define SKYBLUE             clSkyBlue
#define TEAL                  clTeal
#define WHITE                 clWhite
#define YELLOW              clYellow
#define DEFAULT             clDefault

'S/W 개발 > Embarcadero' 카테고리의 다른 글

BDS 단독 실행 프로그램 만들기  (0) 2007.12.06
볼랜드 기본 칼라 Define  (0) 2007.12.06
INI 파일  (0) 2007.12.06
컨트롤 동적 생성..  (1) 2007.12.06
Posted by 가희나희아빠 희자매(가희나희)아빠
TAG 색상
S/W 개발/Embarcadero2007.12.06 10:34
볼랜드에서 제공하는 INI 함수를 이용하기 위해...
IniFiles.hpp 파일을 인크루드 시키고..

#include <IniFiles.hpp>

파일 경로 선언..
#define INI_FILE_IO             ".\\..\\Ini\\Io.ini"

INI 파일을 읽어서.. 화면 캡션 변경...
16진수 처리를 위해.. 약간 수정..
파일 캡션 처리....



쓸경우에는
inifile->ReadString(sSection, sKey, "");
부분을
inifile->WriteString(섹션, 키, 수정값);
방식으로 하면 됨...

if else 보다는 case문이 더 빠름... 그냥.. 귀찮아서.. if else 처리

'S/W 개발 > Embarcadero' 카테고리의 다른 글

볼랜드 기본 칼라 Define  (0) 2007.12.06
INI 파일  (0) 2007.12.06
컨트롤 동적 생성..  (1) 2007.12.06
컨트롤 내부 속성중... 정렬관련.  (0) 2007.12.06
Posted by 가희나희아빠 희자매(가희나희)아빠
TAG ini
S/W 개발/Embarcadero2007.12.06 10:32
우선 헤더에 선언할 컨트롤 변수 선언...

TmLED  *XLed[16];                     // Input Led
TPanel *XPanel_Name[16];         // Input 이름부

그 다음 생성하고자 하는 부분에 생성..
여기에서는 ... 16개씩 처리하도록 함...


그리고 종료하는 부분에... 메모리에서 삭제...



'S/W 개발 > Embarcadero' 카테고리의 다른 글

INI 파일  (0) 2007.12.06
컨트롤 동적 생성..  (1) 2007.12.06
컨트롤 내부 속성중... 정렬관련.  (0) 2007.12.06
[펌] c빌더에서 쓰레드 사용하기  (0) 2007.12.06
Posted by 가희나희아빠 희자매(가희나희)아빠
TAG 컨트롤
S/W 개발/Embarcadero2007.12.06 10:31
THeaderSection::Alignment Property Specifies how text is aligned within the header section.

Class THeaderSection

Syntax

[C++] __property TAlignment Alignment = {read=FAlignment, write=FAlignment};

Description Use Alignment to specify whether the header section text should be left-justified, right-justified, or centered. These are the possible values of Alignment:
ValueMeaning

taLeftJustify

Align text on the left side of the header section.

taCenter

Center text in the header section.

taRightJustify

Align text on the right side of the header section.

'S/W 개발 > Embarcadero' 카테고리의 다른 글

컨트롤 동적 생성..  (1) 2007.12.06
컨트롤 내부 속성중... 정렬관련.  (0) 2007.12.06
[펌] c빌더에서 쓰레드 사용하기  (0) 2007.12.06
[펌] 함수 포인터의 단점  (0) 2007.12.06
Posted by 가희나희아빠 희자매(가희나희)아빠
TAG 컨트롤
S/W 개발/Embarcadero2007.12.06 10:29
아! 쓰레드!
──────

쓰레드.. 아직 윈32하에서, 그리고 빌더에서(혹은 델파이에서 쓰레드)를 써보지 않으신 분들은
이 쓰레드라는 녀석에 대해 상당한 본능적인 공포를 가지고 계신 분도 있을겁니다. (사실 접니다... --)
도스시절에 멀티쓰레드 어플을 만드는 것은 거의 예술의 경지였죠.
아주 가끔씩 통신망에 올라오는 '멀티쓰레드 XXX' 혹은 '멀티태스킹 XXX'를 볼때마다 (여기서 XXX를
이상하게 해석하지 마세요..) 제 눈은 존경과.. 시기와.. 경외감에 차다 못해 두려움마저... 흑흑~~~

하쥐만~! 지금은 X나 X나(포유류 이름) 맘만 먹으면 아무라도 쓰레드를 만들고 또 재밌게 갖고 놀다가
없애버릴 수 있는 아주 부담없는 개념이 되었죠. 물론 api 수준의 쓰레드 지원도 볼만합니다만... 어지러워요!
무신 함수들이 그렇게 많은지.. 헐~
그러나 vcl 차원에서 지원되는 쓰레드는, 물론 이것도 api를 래핑한 것이지만, 그래도 훨 사용하기가 편하답니다.
얼마나 사용하기 편하냐구요? 아따 성질 급하기는... 지금부터 나갑니다.


쓰레드란?
─────

먼저.. 아직 쓰레드가 뭔지를 모르실 분들을 위해, 쓰레드의 일반적인 개념에 대해 아주 간단히 살펴봅시다.
멀티쓰레드란 말을 못들어봤다고 해도, 아마 멀티태스킹이란 말은 다 아실 겁니다. (컴맹도 알던데요!)

저도 원래 전산이론에 빠삭한 도사는 못되기 때문에 정확한 정의는 내리기 힘들고, 일반적으로 멀티쓰레드란
말은 멀티태스킹이란 말과 같은 의미로 쓰입니다. 다시말하면? 쓰레드란 하나의 작업이라고 해석할 수 있다는 거죠.
멀티태스킹이란 말은 동시에 여러개의 어플리케이션을 실행할 수 있다는 뜻이 아닙니다!
사실 멀티태스킹이란 말은 여러개의 '어플리케이션' 이 아닌 여러개의 '작업'을 할 수 있다는 거죠.
말장난 같죠? 그런데 사실입니다.

윈32 커널 하의 어플리케이션은 모두 하나 이상의 쓰레드로 구성되어 있습니다. '하나 이상'이라고 한
것은, 모든 어플리케이션은 디폴트로 하나의 쓰레드가 실행되는 상태란 말입니다. 다시 해석해보면,
이 말은 디폴트로는 하나의 작업만 하지만, 어플리케이션을 설계하는 단계에서 '약간의' 수고를 더 해주면
하나의 어플리케이션이 동시에 둘 이상의 일을 할 수 있다는 뜻이 되죠.
잘 이해가 안되시면, 쉽게 생각해서 하나의 어플리케이션 안에 또하나의 어플리케이션을 돌릴 수 있다고
생각해도 되겠네요.


단계1 : 쓰레드 클래스의 뼉다구를 만들자
────────────────────

C++빌더와 델파이의 쓰레드는, 물론 api 수준의 쓰레드함수들을 그대로 쓸수도 있지만, 역시 oop 언어답게
TThread 클래스가 미리 준비되어 있죠! 요 귀여운놈을 상속받아서 클래스를 구축하면 됩니다.

하지만 이걸 매번 직접 코드를 만들려면 귀찮으니까... C++빌더/델파이의 IDE에서 기본 뼉다구(skeleton)
코드를 만들어주는 기능이 있습니다.
델파이 혹은 C++빌더의 File 메뉴의 가장 위에 있는 New 항목을 클릭해서 나오는 New Item 다이얼로그에서
첫번째 탭에 있는 아이콘들 중에서(여기 보면 어플리케이션 , 컴퍼넌트, 폼, dll, 유닛 등의 항목이 있죠)
'Thread object'가 있답니다. 당근 이걸 클릭! 그럼 다이얼로그가 뜨면서 델파이 혹은 C++빌더가 물어봅니다.
'만들 쓰레드클래스의 이름은 뭘로 할거유?...'
역시 어제와 마찬가지로... 학습의 효과를 높이기 위해, 이름을 이렇게 붙여봅시다.
ImpThread. 조오쵸?

이렇게 해서 만들어진 코드가 다음과 같습니다. 자세히 보실 필요는 없고..
그냥 TThread를 상속받고 있다는 것, 그리고 멤버함수가 뭐뭐인지 정도만 봐두세요.
다음은 C++빌더에서 생성되는 코드입니다.



델파이에서 생성되는 코드는 다음과 같습니다.


사족 : 얼마나 갈켜줄까
───────────

자아.. 이렇게 해서 길쭈구리한 코드들을 포함한 새 유닛이 자동생성되었습니다.
생성됐으면? 그걸로 끝인가? 써먹어야지! ^^

사실 이 쓰레드라는 개념은 자그마한 팁이 아니라, 꽤나 복잡한 기술이기도 하고, 또 활용도도 말할 수도 없이
많습니다. 글구 이 TThread 클래스의 메소드와 프로퍼티만 해도 한두개가 아니랍니다. 그럴수 밖에 없는 것이,
sdk의 그 많은 쓰레드 관련 api를 대부분 클래스화했으니...

그럼 임프는 오늘 과연 이 쓰레드에 관련한 모든 것을 다 갈쳐줄수 있을까요?
대답은... 택도 엄따~! 입니다. ^^;;;
쓰레드를 제대로 설명하려면 분량도 웬만한 책 한권은 나올정도인데다가, 무엇보다도... 저도 다 모릅니다! (쿵~!)
그래서.. 이러이러한 관계로.. 오늘은 아주~! 간단한, 하지만 작은 예제 하나를 들어보면서 워밍업만 해봅시다.



뭘 해보까
─────

뭘 하느냐... 아 기다려봐요~
이런 경험이 있을겁니다. for문을 돌리면서 메시지를 처리하려면?
for 루프를 돌고 있는 동안에는 어플리케이션 전체가 busy 상태이므로 특별한 처리를 해주지 않으면 어플리케이션에
넘어오는 메시지들은 전혀 처리되지 못한채 메시지큐에 차곡차곡 쌓이죠. 이 상태가 바로 '응답없음' 상태랍니다.
보통은 이걸 간단히 해결하기 위해 for 루프 내에 Application->ProcessMessages()를 삽입하는데..
이 메소드는 잠시 현재 작업을 잠시 중지시켜놓고 메시지큐에 쌓인 메시지들을 처리하는 역할을 하죠.
문제는.. 이 방식이 상당히 느리단 거죠. 거기다 for 루프내의 코드가 상당히 복잡할 경우 몇번씩이나 같은
Application->ProcessMessages()를 삽입해야 하고.. 느리니까 당연히 시간 정확도가 요구되는 작업에는 쓰면
안됩니다. 이럴때 바로 쓰레드를 씁니다. 물론 딴데도 쓰지만, 여기서 쓰레드의 활용도를 간단한 예제로 설명하는데는
아주 딱이겠네요.


단계 2 : 쓰레드 클래스의 생성자 작성
──────────────────

자아.. 그럼 코드를 작성해봅시다. 아까 만든 ImpThread 그대로 있죠?
거기다 장난을 쳐봅시다.

C++빌더에서는, 헤더에 있는 생성자 선언을 조금 수정해줍니다.
__fastcall TImpThread(bool CreateSuspended);
에서,
__fastcall TImpThread(void);
이렇게 바꿉니다.

마찬가지로, 생성자의 바디 부분도 조금 수정하고 코드 한줄을 추가합니다.


생성자에서 베이스 클래스인 TThread 생성자의 인자로 false를 넘겨주도록 수정한 것을 봐두세요.
TThread의 생성자가 갖는 CreateSuspended 인자는 쓰레드 객체만 생성해두고 실제로 쓰레드를 실행하지는 않고
대기할 것인가의 여부를 결정합니다. 따라서 false를 넘겨주면 생성된 직후에 바로 실행이 시작됩니다.

한편, 델파이에서는...
똑같이 쓰레드 오브젝트를 생성해도, C++빌더에서는 생성자 코드까지 만들어주지만 델파이에서는 생성자를
만들어주지 않습니다. 그러니까 델파이를 쓴다면 생성자 선언과 바디를 직접 만들어줘야 하지요.

interface 섹션의 TImpThread 클래스 선언에, public을 추가하고 다음과 같이 생성자를 코딩해줍니다.
constructor Create;

그리고 위에서 선언한 생성자의 바디를 implementation에 추가합니다.
constructor TImpThread.Create;
begin
  inherited Create(false);
  Priority := tpTimeCritical;
end;

베이스 클래스인 TThread의 생성자로 false를 넘겨준 것은 위의 C++의 경우와 같은 이유입니다.
그리고 역시 똑같이 한줄 더 추가했습니다.

뼉다구 코드에다가 딱 한줄 추가한겁니다. 그쵸?
여기서 Priority는 TThread 클래스의 프로퍼티로서.. 현재 쓰레드의 작업 우선순위를 말합니다.
tpTimeCritical은 가장 높은 단계로서, 시간의 오차가 최소화되어야 하거나 윈도우즈가 아무리 바쁜 상황이라도
반드시 수행되어야 할 작업을 할때 이 tpTimeCritical을 지정합니다. 반대로 가장 낮은 순위는 tpIdle이고, 그 위로
tpLowest, tpLower, tpNormal, tpHigher, tpHighest, 그리고 tpTimeCritical까지 지정이 가능합니다.
그럼, 여기서 tpTimeCritical로 지정한 이유는? 대단한 걸 해보려고? 아닙니다.
그냥 기분이 나서 해봤습니다. 따지지 마세요.


단계 3 : 쓰레드 클래스의 Execute 메소드 작성
───────────────────────

그리고.. 이번엔 그다음 뼉다구인 Execute() 메소드의 바디에다 코드를 작성해 봅시다. 바로 이 Execute 메소드가
쓰레드 자체입니다. 별도의 쓰레드로 나누어 작업을 시킬 바로 그 작업을 이 Execute 메소드에게 시켜먹으면 되는
겁니다. (참고로 생성자나 파괴자, 그외 다른 모든 메소드들은 쓰레드로 동작하지 않으며 프로그램의 메인 쓰레드에서
동작합니다)

먼저 TImpThread 클래스의 선언에 private 섹션에 정수형 변수 qq를 하나 추가합니다. C++이라면,
class TImpThread : public TThread
{
private:
    int qq;
    ...
이렇게 될 것이고,  델파이라면,
  TImpThread = class(TThread)
  private
    qq: integer;
    ...
이렇게 되겠죠.

이제 Execute 메소드에 다음과 같이 코드를 추가해봅시다.
C++에서는,


델파이에서는,

여기서...Terminated가 뭘까요?
Terminated는 속성으로서 현재 쓰레드가 작업중인지의 여부를 가리키는 boolean형 속성입니다.
따라서 Terminated = true가 되는 순간이 현재 쓰레드의 작업을 마쳐야 할 시점이라고 생각하면 되겠습니다.

그러니까.. qq의 값을 1씩 증가시키다가 100으로 나눠 떨어지면 폼의 캡션에 그 값을 표시하고 계속 실행하라...
정도 되겠습니다. 그러면 폼1의 캡션이 미친X처럼 파라라라라락~~~ 카운팅되고 있는 숫자로 정신없는 상황이
눈에 선하죠? ^^


단계 4 : Synchronize()
────────────

여기서 쓰레드 프로그래밍에서 반드시 짚고 넘어가야 할 중요한 오류가 하나 있습니다.
바로 폼의 캡션을 수정하는 부분입니다.
TThread 객체의 Execute에서는 VCL의 폼 관련 루틴은 절대로 직접 접근해서는 안되며, 직접 접근할 수 있는
것은 서브 쓰레드가 아닌 프로그램의 디폴트 쓰레드(메인 쓰레드) 뿐입니다.

그러면, 지금 작성하고 있던 예제의 경우 폼에다가 표시하는 것이 목적인데 방법이 없으면 안되겠죠?
이럴 때 쓸 수 있는 것이 TThread 클래스의 Synchronize() 함수입니다. 이 함수는 Execute() 실행중에
반드시 실행해야 하는 루틴을 디폴트 쓰레드로 실행을 위임합니다. 필요한 루틴들을 별도의 함수로 만들어
분리한 후, 그 함수의 포인터를 Synchronize() 함수로 넘기면 된답니다.

다음과 같이 함수를 추가합니다. 클래스 멤버니까 당연히 클래스 선언 내에 함수 선언도 해주어야겠지요.

그리고 Execute() 내에서 폼에 바로 접근하는 부분도 Synchronize()를 호출하도록 고쳐주어야 합니다.


자아.. 한가지만 더 하고 이 쓰레드 유닛은 끝냅시다. 뭐냐구요? 위에서 Form1을 억세스 했잖아요.
그러니 당연히 인클루드 해야죠. 안그럼 컴파일러가 삐지겠죠? #include "Unit1.h"
이제.. 쓰레드 클래스는 다 만들었습니다. 뭐이리 간단하냐구요? 그러니까 빌더가 조은 거지!
그럼.. 이제부터 실제로 이 클래스의 객체를 생성하고 쓰레드를 시작하는 코드를 작성해봅시다.


단계 5 : 완성된 쓰레드의 사용
──────────────

프로젝트의 메인폼인 Form1에 버튼 두개만 따캉~! 따캉~! 하고 놔봅시다.
그리고 각각 캡션은 "시작!", "종료!" 라고 붙입니다. 그런후에..
"시작!"이라고 캡션을 넣은 Button1을 더블클릭해서 OnClick 핸들러를 만들고,
그안에 코드를 작성합시다.


근데 여기서 써먹은 ImpThread라는 TImpThread 객체는 어디에도 아직 만들지 않았죠? 폼과는 달리 쓰레드는
전역적으로 선언되는 포인터를 자동으로 만들어주지 않습니다. 그러니 직접 선언해줍시다. 어디다가?
그것도 일일이 갈켜줘야해요? 뭐, 폼클래스에 집어넣든지 혹은 유닛에 전역적으로 선언하든지 관계없지만,
폼클래스가 지저분한건 딱 질색이니까 폼 유닛의 위 Button1Click() 함수 바로 위에다가 선언해줍시다.
딴데 하고 싶다고요? 누가 말립니까?

TImpThread *ImpThread; // C++
ImpThread: TImpThread; // 델파이

그리고.. 이번엔 Button2("종료!"라고 캡션을 준 버튼)을 더블클릭해서 핸들러를 작성해봅시다.

뭐.. 간단하지요? 별로 설명할게 없어보입니다만.. 굳이 사족을 달자면, Terminate()는 당연히 TThread의
메소드로서, 쓰레드의 실행을 중지시키는 거죠. 그리고 마지막으로 더이상 쓸모가 없어진 쓰레드를 삭제하고요.

마지막 단계 : 실행해보잣!
─────────────

끝입니다. 설명은 장황했지만, 실제로 작성한 코드는 불과 열줄이 채 되지 않죠?
그런데도 실행해보면, 캡션은 열심히 미친 X 처럼 숫자를 카운트하고 있고, 그동안에도 마치 어플리케이션은
아무 일도 안하고 있는 것처럼 메시지를 잘 처리합니다. 대표적으로 캡션바를 드래그해보면, 바쁘게 카운팅을
하는 중인데도 불구하고 드래깅하는 마우스메시지에 제깍제깍 반응합니다. 신기하지요? ^^


결 론
───

오늘의 팁은 여기까지입니다.
요약하자면.. 사실 쓰레드는 아주 복잡한 내부 처리를 거치는 아주 큰 기술입니다. 다루기도 쉽지 않구요.
하지만 vcl에서는 이 쓰레드 개념을 적절히 래핑하여 아주 재미있게 장난감처럼 갖고놀 수 있는 클래스로
만들어놨습니다.

월요일엔 이 쓰레드를 활용하는 다른 예를 들어보겠습니다.
사실 오늘 쓰레드를 설명한 것도, 월요일에 진행할 다음 팁을 쓰는데 쓰레드 개념이 필수적이기 때문입니다.
뭔지 미리 공개하지는 않겠고.. 아주 많은 분들이 애타게 기다리는 팁이란 것만 귀띔해두죠.
벌써 여기저기에서 관련 질문만 여러번 올라왔던 전력이 있는 팁인데, 아직까지 제대로된 답변이 올라온 걸
본적이 없거든요.

// 볼랜드 포럼에서 발췌..
Posted by 가희나희아빠 희자매(가희나희)아빠
S/W 개발/Embarcadero2007.12.06 10:29
함수 포인터의 단점은 다음과 같습니다.

1) 디버깅이 어렵다.
(콜백함수나 이벤트 핸들링의 경우가 아니고) 함수 포인터를 사용하여 수동으로 호출하는 함수가 몇십개나 된다고 가정해 봅시다.
분 기하기전에 브레이크 포인트를 걸고 어떤 함수로 분기하고자하는지 알고자 할때는 너무 어렵죠. 예를 들어 변수 a라면 값을 바로 알아 낼 수 있지만, 함수 포인터 p라면 그 값이 어떤 함수를 가리키는지 알 수가 없죠. 이럴때는 분기 가능한 모든 함수에 브레이크 포인터를 거는 수밖에 없습니다.

2) 속도가 느리다.
ANSI C 라이브러리에서 함수 포인터를 사용하는 대표적인 함수인 qsort의 경우를 생각해 봅시다. 대소 비교를 위해서 fcmp라는 함수 포인터를 사용하는 데, 이건 qsort 내부에서 대소 비교가 필요할 때마다 매번 호출됩니다.
실제 정렬하는 시간보다 함수 호출을 위한 비용이 훨씬 크게 되어버립니다.

그래서 ANSI C++ STL에서 이런 문제점을 해결하기 위해 만든 것이 함수 포인터를 대신하는 함수 객체(function object)입니다.
함수 객체란 멤버 함수로 함수 하나만 들어 있는 매우 간단한 클래스입니다.
클래스이기 때문에 당연히 인라이닝할 수 있지요.
그래서, STL의 sort가 C의 qsort보다 무려 67000배나 빠릅니다!

콜백함수나 이벤트 핸들링과 같이 반드시 필요한 경우나,
함수 포인터를 써야만 코드가 매우 간결해지는 경우외에는 가능한 한 사용하지 않는 것이 좋습니다.

출처 : 볼랜드포럼
Posted by 가희나희아빠 희자매(가희나희)아빠
TAG 포인터
S/W 개발/Embarcadero2007.12.06 10:28
#include<stdio.h>
#include<conio.h>

//------------------------------------------------------------------
int* (*Func1())();
int* (*Func1_1())();
int* (*Func1_2())();
int* (*Func1_3())();
int* Func2();
int* Func2_1();
int* Func2_2();

#define N 8
int *(*(*a[N])())() = {Func1,Func1_1,Func1_2,Func1_3,NULL,};
/*
위는 배열 a를 선언/정의한 것이며 해석해보면 아래와 같습니다.
형을 해석할 때는 가장 안쪽 괄호부터 합니다.
*a[N] : 원소수가 N개인 포인터 배열 a
       , 이 배열의 각원소인 포인터가 무엇을 가리키느냐는 다음 괄호를 해석.
*() : 포인터를 반환(return)하는 함수
      ,위의 배열 각 원소가 바로 이 함수형으로 정의된 함수를 가리킴
      ,그리고 이 함수가 포인터를 반환한다고 했는데 그 포인터가 어떤 것인지는 다음을 해석
int *() : int*를 반환하는 함수
       ,위의 함수가 반환하는 포인터는 이 함수형으로 정의된 함수를 가리킴.

참고로, 이런 복잡한 형은 거의 사용하지 않습니다.
이해가 잘 안되면 그냥 넘어가시기를 권합니다.
프로그램 경력이 늘면 차츰 쉽게 이해가 됩니다.
다만, 아래 1,2는 알고 계시는게 좋습니다.
1. 포인터 배열과 배열을 가리키는 포인터의 구별
int *arr[16]; 포인터 배열 arr(원소수가 16개이고 각 원소는 포인터(int*))
int (*arr)[16]; 배열(원소수가 16개이고 각원소는 int형)을 가리키는 포인터 변수 arr

2. 포인터를 반환하는 함수와 함수를 가리키는 포인터의 구별
int* Func(float); float형 매개변수 하나를 취하고 포인터를(int*)를 반환하는 함수 Func
int (*Func)(float); 함수(float형 매개변수 하나를 취하고 int를 return)를 가리키는 포인터 Func

3. 어떤 함수가 있을 때 이를 가리키는 포인터 선언/정의 방법
int* Func(float); 함수가 있다고 하면
우선 함수이름 부분을 괄호로 묶습니다: int* (Func)(float);
다음으로 함수이름 바로 앞에 *를 붙입니다: int* (*Func)(float);
마지막으로 이름을 중복되지 않은 원하는 것으로 지정합니다: int* (*pFunc)(float);

4. 특정형으로의 형변환 방법
int* (*Func)(float)로 형변환 하려면
우선 변수의 이름을 지웁니다: int* (*)(float)
전체를 괄호로 묶습니다: (int* (*)(float))

5. typedef
int* (*Func)(float);
위와 같은 형을 만들려면 앞에 typedef를 붙인다음: typedef int* (*Func)(float);
형의 이름을 원하는 것으로 정해주면 됩니다:  typedef int* (*FuncPointerType)(float);
*/

//출처 - 볼랜드포럼

'S/W 개발 > Embarcadero' 카테고리의 다른 글

[펌] 함수 포인터의 단점  (0) 2007.12.06
[펌]함수 포인터 복합선언?  (0) 2007.12.06
pas 화일을 볼랜드 C++에서 쓸때..  (0) 2007.12.06
BDS에서 TRACE 기능 사용하기...  (0) 2007.12.06
Posted by 가희나희아빠 희자매(가희나희)아빠
TAG 포인터

티스토리 툴바