20141027 (C++ 객체 초기화, 대입연산자, 배열 연산자, ARM ADS)

166일차










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

C++

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







------- 객체 초기화


객체를 초기화하는 방법이 두 가지 있습니다.

다음 예제 확인


예제)

//ImproveInit.cpp

#include <iostream>


using namespace std;


class AAA

{

private:

int num;


public:

AAA(int n = 0) : num(n) // default 생성자

{

cout << "AAA(int n = 0)" << endl;

}


AAA(const AAA& ref) : num(ref.num) // 받은 인자로 초기화하는 생성자

{

cout << "AAA(const AAA& ref)" << endl;

}


AAA& operator=(const AAA& ref) // 대입 연산자

{

num = ref.num;

cout << "operator=(const AAA& ref)" << endl;

return *this;

}

};


class BBB

{

private:

AAA mem;


public:

BBB(const AAA& ref) : mem(ref) // 생성자로 초기화

{

}

};


class CCC

{

private:

AAA mem;


public:

CCC(const AAA& ref)

{

mem = ref; // 대입 연산자로 초기화

}

};


int main()

{

AAA obj1(12);

cout << "*************************" << endl;


BBB obj2(obj1);

cout << "*************************" << endl;


CCC obj3(obj1);

cout << "*************************" << endl;


return 0;

}

결과



위의 결과 화면에서 확인할 수 있듯이,

생성자로 초기화한 것과, 대입 연산자로 초시화한 것이

속도 차이가 분명하다.


생성자로 초기화한 것은 한 번(생성자만 호출),

대입 연산자로 초기화한 것은 두 번(생성자, 대입 연산자 호출)

실행한다.











------- 대입 연산자, const


다음 예제를 보고 하겠습니다.


예제)

#include <iostream>

#include <cstdlib>


using namespace std;


class BoundCheckIntArray

{

private:

int * arr;

int arrlen;


BoundCheckIntArray(const BoundCheckIntArray& arr)

{ }

BoundCheckIntArray& operator=(const BoundCheckIntArray& ref)

{ }

public:

BoundCheckIntArray(int len) : arrlen(len) // 생성자

{

arr = new int[len];

}


int& operator[] (int idx) // 배열 연산자

{

if(idx < 0 || idx >= arrlen)

{

cout << "Array index out of bound exception" << endl;

exit(1);

}

return arr[idx];

}

/*

int operator[] (int idx) const // 배열 연산자 (const, 오버로딩)

{

if(idx < 0 || idx >= arrlen)

{

cout << "Array index out of bound exception" << endl;

exit(1);

}

return arr[idx];

}

*/

int GetArrLen() const

{

return arrlen;

}


~BoundCheckIntArray()

{

delete []arr;

}

};


void ShowAllData(const BoundCheckIntArray& ref)

{

int len = ref.GetArrLen();

for(int idx = 00; idx < len; ++idx)

{

cout << ref[idx] << endl; // 배열 연산자  호출

}

}


int main()

{

BoundCheckIntArray arr(5);


for(int i = 0; i<5; ++i)

{

arr[i] = (i+1) * 11;

}


ShowAllData(arr);


return 0;

}


이 예제는 컴파일 시, 에러입니다.

이유는 ShowAllData 함수에서 배열 연산자 호출하는 부분이 있는데,

인수로 받는 ref를 보시면 const로 선언이 된 것을 확인할 수 있습니다.

따라서 이 함수에서 ref 관련 호출할 수 있는 함수는 const로 선언되어야만

호출 가능합니다.


따라서 위에 주석을 제거하면 operator= 이 const로 오버로딩되어

정상적으로 동작하게 됩니다.














------- 배열 연산자


아래 예제를 봅시다.


예제)

#include <iostream>

#include <cstdlib>


using namespace std;


class Point

{

private:

int xpos;

int ypos;


public:

Point(int x = 0, int y = 0) : xpos(x), ypos(y)

{ }

friend ostream& operator<<(ostream& os, const Point& pos); // << 연산자 friend

};


ostream& operator<<(ostream& os, const Point& pos) // << 연산자 정의

{

os << '[' << pos.xpos << ", " << pos.ypos << "]" << endl;

return os;

}



class BoundCheckPointArray

{

private:

Point * arr;

int arrlen;


BoundCheckPointArray(const BoundCheckPointArray& arr)

{ }

BoundCheckPointArray& operator=(const BoundCheckPointArray& arr)

{ }


public:

BoundCheckPointArray(int len) : arrlen(len) // 생성자

{

arr = new Point[len]; // 멤버 변수 arr 메모리 할당

}


Point& operator[](int idx) // 배열 연산자

{

if(idx < 0 || idx >= arrlen)

{

cout << "Array index out of bound exception" << endl;

exit(1);

}

return arr[idx];

}


Point operator[] (int idx) const // 배열 연산자

{

if(idx < 0 || idx >= arrlen)

{

cout << "Array index out of bound exception" << endl;

exit(1);

}

return arr[idx];

}


int GetArrLen() const

{

return arrlen;

}

~BoundCheckPointArray()

{

delete []arr;

}

};


int main()

{

BoundCheckPointArray arr(3);


arr[0] = Point(3, 4);

arr[1] = Point(5, 6);

arr[2] = Point(7, 8);


for(int i = 0; i < arr.GetArrLen(); ++i)

{

cout << arr[i];

}


return 0;

}

결과



이 소스에서

arr[0] = Point(3, 4);

명령이  배열연산자에 의해 실행되는 과정을 보면


1. Point 객체 생성 (생성자에 의해 객체 멤버 값은 xpos = 3, ypos = 4)


Point(int x = 0, int y = 0) : xpos(x), ypos(y)



2. arr[0]   ==  arr.operator[](0)   그래서 []함수? 호출


Point& operator[](int idx) // 배열 연산자

{

if(idx < 0 || idx >= arrlen)

{

cout << "Array index out of bound exception" << endl;

exit(1);

}

return arr[idx];

}



3. return 값이 Point& 형이므로 결국 arr.arr[0] 변수를 가리키므로

arr.arr[0]에 값이 대입된다.















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

ARM

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




------- ARM ADS


ARM Developer Suite 라는 줄임말로 ARM 사에서 제작한 유료 C컴파일러

현재는 단종되었다고 합니다.




---- 설치법


- SETUP.EXE를 실행
















- 설치가 끝나면 아래 라이센스 관련 창이 뜹니다.







- 설치 파일이 있던 곳에 가면 CRACK이란 폴더에 위치하고 있습니다.






- 다음과 같은 결과가 보이면 다음으로 갑니다.








- 설치가 완료되면 바탕화면에 바로가기가 생성되지 않기 때문에

C:\Program Files\ARM\ADSv1.2\Bin 으로 가서 IDE.exe 바로가기를 만드셔서 사용하시거나

시작 -> Programs -> ARM Developer Suite v1.2 -> CodeWarrior for ARM Developer Suite 실행하면 됩니다.




- cmd 창에서 버전 확인


ARM 사에서는 문제점들을 보완한 패치버전을 계속해서 내어놓고 있었다고 합니다.

최신 버전으로 업데이트하는 방법을 알아볼 예정인데요

http://www.arm.com/support/downloads/info/4554.html 에서 받을 수 있다는데

현재는 지원이 끝났나 봅니다.


그런데 구하기 쉽더군요ㅋㅋㅋㅋ

4554_ADS12_848_Windows.exe




- 아래와 같이 실행



- 버전이 상승된 걸 확인할 수 있습니다.








---- 실행법


- 먼저 실행하기 전에 예제 파일을 받아옵니다.

http://cpu.kongju.ac.kr/frame3.htm 에 가셔서

책 관련 자료실 -> 166번 게시글 (ADS v1.2용의 C언어 예제 파일)

예제 파일을 받아 ADS 가 설치 된 곳에 함께 둡니다.




- IDE.exe 나 시작프로그램에 CodeWarrior... 실행










- ADS v1.2용 C언어 예제 프로그램에서 항상 공통적으로 사용하는 스타트업 파일이 3개 있는데, 이것들을

하나의 그룹으로 묶어서 등록하여 두면 편리하므로 그룹을 생성합니다.







- Cstartup.s 열기





- 나머지 두 파일도 추가








- 이제 실행할 예제 소스를 추가합니다.



- Xtest01_1.c


소스 내용은


#include "AT91SAM7S256.h"

#include "lib_AT91SAM7S256.h"

#include "OK7S256ads.h"


int main(void)

{

  MCU_initialize(); // initialize AT91SAM7S256 & kit


  while(1)

    { Beep(); // beep 


      LED_on(LED1); // LED1 on 

      Delay_ms(1000);

      LED_off(LED1); // LED1 off

      Delay_ms(1000);

      

      LED_on(LED2); // LED2 on 

      Delay_ms(1000);

      LED_off(LED2); // LED2 off

      Delay_ms(1000);

      

      LED_on(LED2|LED1); // LED2 and LED1 on 

      Delay_ms(1000);

      LED_off(LED2|LED1); // LED2 and LED1 off

      Delay_ms(1000);

    }

}

로 LED 2개를 껐다 켰다 합니다.



- 여기까지 새로운 프로젝트 Test.mcp가 만들어지고 여기에 3개의 스타트업 파일과 사용자 프로그램을 등록 완료하였습니다.



- Tip> 프로젝트에서는 타겟을 기본적으로 DebugRel 폴더로 지정한다. Debug 폴더로 하면 최종 출력 파일에

          디버그 정보를 포함하는데 주력하며 최적화 기능은 희생되는데 비해 Release 폴더로 하면 반대로 최

          적화 기능에 주력하고 디버그 정보는 포함하지 않는다. 그러나, DebugRel 폴더로 지정하면 이것들의

          중간 정도로 처리된다.



- 새로운 프로젝트의 환경 설정

    프로젝트의 프로그래밍 환경설정을 시작하려면 프로젝트 창에서 DebugRel Settings.. 아이콘을 누르거나

  Edit탭의 DebugRel Settings... 메뉴를 선택하거나 Alt+F7단축키를 이용합니다.











- 위에 혹시나 잘 안보이는 글자는 " 0x00000000 ", " 0x00200000 " 입니다.










- 에디터를 사용할 때, 탭 간격 조절






사용자 프로그램을 더블클릭하게 되면 파일 내용을 볼 수 있습니다.

- 컴파일은 프로젝트 창에서 사용자 프로그램을 오른쪽 마우스 클릭하고 Compile을 누르고,

- 컴파일 및 링크를 수행하려면 프로젝트 창에서 Make 아이콘을 누르거나 메인화면에 있는 Make아이콘을

   눌러도 되며, Project탭에서 Make메뉴를 선택하거나 F7단축키를 이용하는 방법이 있습니다.




- 컴파일시 entry 가 없다고 warning?이 뜨던데, 삼바로 arm에 넣으면 잘 돌아갑니다ㅋㅋㅋㅋ

bin 파일 위치는 프로젝트 이름을 test로 했으니, 내문서 -> test -> test_Data -> DebugRel 에 있습니다.



출처 : http://alisa2304.tistory.com/35








------- Cstartup.s 소스 분석



;-------------------------------- ; <- 주석입니다.

;- ARM Core Mode and Status Bits

;--------------------------------

IRQ_STACK_SIZE EQU (3*8*4) ; 2 words per interrupt priority level

;요기는 #define과 같은 맥락으로

;IRQ_STACK_SIZE 는 (3*8*4)로 치환한다는 뜻이겠죠?


ARM_MODE_USER EQU 0x10

ARM_MODE_FIQ EQU 0x11

ARM_MODE_IRQ EQU 0x12

ARM_MODE_SVC EQU 0x13

ARM_MODE_ABORT EQU 0x17

ARM_MODE_UNDEF EQU 0x1B

ARM_MODE_SYS EQU 0x1F


I_BIT EQU 0x80

F_BIT EQU 0x40

T_BIT EQU 0x20


;------------------------------------------------------------------------------

;- Area Definition

;------------------------------------------------------------------------------

AREA  reset, CODE, READONLY ; 읽기전용, CODE 영역

ENTRY

EXPORT entry ; entry를 외부에 보이게.


...


entry

B InitReset ; 0x00 Reset handler

; B 는 jmp 와 같은 명령으로 InitReset으로 가볼까요?

undefvec

B undefvec ; 0x04 Undefined Instruction

...



;--------------------

;- The reset handler

;--------------------

InitReset ; 여기까지 날아왔습니다~

...

IMPORT AT91F_LowLevelInit ; 외부에서 저 함수를 가져온다는 명령.


;- minimum  C initialization

ldr r13,=0x00204000 ; temporary stack in internal RAM

; ldr은 LoaD Register라는 명령으로 r13 Reg 에 0x00204000 값을 넣습니다.

ldr r0,=AT91F_LowLevelInit

; r0 Reg 에 함수 주소?를 넣었어요

mov lr, pc

bx r0

; bx 는 실행, 분기 기능으로 r0에 있는 것을 실행한다는 뜻이니 AT91F_LowLevelInit 을 실행합니다.




- AT91F_LowLevelInit은 Cstartup_SAM7.c 에 정의되어 있습니다.


void AT91F_LowLevelInit(void)

{

  int i;

  AT91PS_PMC pPMC = AT91C_BASE_PMC;

...





오늘은 여기까지... 얼마 남지 않은 시간. 무어싰게 열심히 마무리 합시다!!!

설정

트랙백

댓글