--------------
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 에서 받을 수 있다는데
현재는 지원이 끝났나 봅니다.
그런데 구하기 쉽더군요ㅋㅋㅋㅋ
- 아래와 같이 실행
- 버전이 상승된 걸 확인할 수 있습니다.
---- 실행법
- 먼저 실행하기 전에 예제 파일을 받아옵니다.
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에 넣으면 잘 돌아가지만,
설정하면 warning이 없어집니다.
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;
...
오늘은 여기까지... 얼마 남지 않은 시간. 무어싰게 열심히 마무리 합시다!!!
'코스웨어 > 14년 스마트컨트롤러' 카테고리의 다른 글
[이경진] ARM main (0) | 2014.10.29 |
---|---|
ARM 헤더파일 Define 김재성 (0) | 2014.10.29 |
ARM 소스코딩 (0) | 2014.10.29 |
2014.10.28/ 일일 교육 보고 - 오두환 (7) | 2014.10.28 |
20141024서상우보고서 (8) | 2014.10.26 |
업무일지 박영주 (8) | 2014.10.23 |
20141022 일일업무보고서 11번 문대영 (8) | 2014.10.22 |
2014년 10월 21일 일일업무 출석번호 9번 김해성 (9) | 2014.10.21 |