ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 20141027 (C++ 객체 초기화, 대입연산자, 배열 연산자, ARM ADS)
    부산IT학원/스마트컨트롤러 2014. 10. 27. 17:28

    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;

    ...





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

Designed by Tistory.