본문 바로가기

무언가 만들기 위한 지식/C,C++,Embedded C

[C,C++,Embedded C] About "const"

c나 c++을 하다보면 은근히 접하게 되나 가끔 사용에 있어서 헷갈릴때가 있다.
그래서 const에 대해 이것저것 찾아보고, 배우던 도중 여러가지를 알게 되었다.

[1] 먼저 C에서 쓰이는 C언어에 대해 언급하려한다.

가장 기본적인 const의 용법은 상수화 시키는 것이다. 이는 곧 값을 변경할 수 없음을 말한다.
이는 변수에 사용함에 있어, 위치에 따라 값을 고정시킬 것인지, 포인터 주소값을 고정시킬 것인지 정하게 된다.

[작성환경
: Window XP  작성툴 : Visual Studio 6.0   컴파일러 : Visual Studio 6.0 사용언어 : C]

위의 테스트로 다양한 사실을 알 수 있다.
위 선언을 보면
3 Line에서는 const를 변수명 바로 앞에 선언하였다. 이를 통하여 iPoint는 포인터의 주소값을 변경할 수가 없다.
5 Line의 경우 const가 연속으로 들어갔다. int *앞에 들어간 const는 포인터의 값의 변경을 막아준다.

즉 const는 위치와 쓰임에 따라,
1. 변수를 상수화 한다.
2. 포인터 변수의 포인터 자체(주소값)을 상수화 한다.
3. 포인터 변수가 가리키는 값을 상수화 한다.

세 가지로 분류가 가능하다.

9, 11, 12 Line처럼 const로 상수화된 값들을 억지로 바꾸려고 하면 compile error가 발생한다.
특히 q변수의 경우 바로 접근하면 수정이 가능하나, 포인터를 이용하면 접근이 불가한 모습을 명확히 확인할 수 있다.

위 코드에서 흥미로운 점이 또하나 있는데, 그건 바로 초기화 부분이다.
메인 함수 내부에서 초기화한 testInit2의 경우(13 Line) 출력한 초기화 값이 쓰레기값이 나오지만,
메인 함수 외부에서 전역변수로 선언된 testInit1의 경우 (6 Line) 출력한 초기화 값이 0으로 설정되었다.


이 점은 코드를 작성할때 유의하여야 하고, 알아두면 이런저런 구조면에서 도움이 된다.

[2] 다음 C++의 클래스에서의 멤버함수 const에 대해 알아보자.

[작성환경 : Window XP  작성툴 : Visual Studio 6.0   컴파일러 : Visual Studio 6.0 사용언어 : C++]


6 Line에서 클래스 cal 내부변수에 const선언을 하였고,
23 Line에서 함수에 const선언을 하였다. 어떤 결과를 나오는지 알아보자.
아시다시피 const의 경우 한번 선언하면 그 후 수정이 불가능하다.
그러나 생성자에서 멤버 이니셜라이져를 통해 가능하다.
9 Line에서 : 뒤에 쓰여진 기법은 메모리가 할당되고 실제로 생성자가 실행되기 이전에 실행된다.
이 방법을 통해서 const선언된 멤버 변수의 초기화가 가능해 진다. (멤버이니셜라이즈라고 함)
23 Line에서는 함수 인자 뒤에 const선언을 하였다. 이는 바로 멤버함수의 const선언인데,
이 경우 특징은
1. 멤버변수의 값이 변경되면 compile Error을 발생시킨다.
2. 상수화되지 않은 함수의 호출을 허용하지 않는다.
3. 멤버 변수의 포인터를 리턴을 허용하지 않는다.

2, 3의 경우 상수화된(const 선언된) 함수 내부에서 멤버변수의 변경을 초래할 가능성을 배제하는 것이다.

21 Line의 경우 const 멤버변수를 수정하려하는 과정에서 error를 발생시키고,
24 Line의 경우 const 멤버함수 내에서 일반함수를 호출함에 있어서 compile Error를 발생시킨다.
(const 함수 내부에서는 const함수만이 사용이 가능하다.)

추가적으로 객체 자체에도 const선언이 가능하다.
이 경우, 멤버 변수의 경우 절대적으로 조작이 불가능하며, 상수화된 멤버 변수만 호출이 가능해 진다.

또한 선언시 Overloading이 가능하다.
단 이때 상수화되지 않은 함수가, 상수화된 함수보다 우선순위를 갖으며 실행된다.

mutable 이란 명령어가 있다. 멤버 변수에 이 선언을 하게 되면 const 멤버 함수 일지라도
    해당 멤버 변수의 값을 수정할 수 있다.
    (위에서 언급했듯이 const 선언된 멤버함수는 일반 멤버 변수의 값을 바꿀 수 없다. - compile error)

[3] Embedded C에서 const의 중요성을 알아보자.

const의 의미는 C에서 말했다시피 상수화 하여 수정하지 못하게 하는 것이다. 즉 상수화가 되면 데이터를 읽어올때, Load만 하면되고 write가 불가능한 RO-DATA영역으로 가게 된다.

"여기서 잠깐 알아두어야 할 것"

XIP(eXecute In Place) :  Rom 상에서 존재하는 실행파일(부트코드)를 통해 부팅이 된다. 이때는 RO-Data와 실행파일(부트코드)는 ROM상에 존재하고, 바뀌어야하는 변수들 즉 RW-Data는 Ram상으로 복사! 되어 메모리를 사용하게 된다.

RAM Loading : 어딘가에 존재하는 실행파일(부트코드)을 Ram으로 복사한 후 수행한다. 이때는 RO-Data부터 RW-Data, BSS영역이 모두 RAM상에 존재한다. 가장큰 예로 ROM없이, NAND 플래쉬를 이용하여 부팅하는 경우를 들 수 있다. 이 경우 NAND 만으로는 부팅이 않되기 때문에 RAM으로 복사후 처리한다. (요즘 많이 쓰이는 기법이라고 함.)

Const는 여기서 메모리 최적화!에서 쓰인다.
단 위 박스의 두 가지 방식중에 XIP방식에서 적용된다.
XIP에서,
const를 통하여 데이터 영역을 RO(Read Only)-data로 바꿔주면  const 변수가 ram으로 이동되는 현상이 발생하지 않는다. 이 경우 불필요하게 이동도 일어나지 않으며, 메모리도 절약할 수 있다. 참고되는 불변하는 큰 배열의 경우 성능 속도 면에서 아주 큰 차이가 발생하게 되므로, 고정된 값은 const를 이용하는 습관이 필요하다.

(단 언제나 XIP방식일 경우이다. ram loading의 경우 어차피 모든영역이 ram상으로 올려지기 때문에 상관이 없다.)