컴파일러는 변수에 메모리를 할당하고, 할당된 메모리와 변수를 연결 한다.
변수와 할당된 메모리, 그리고 메모리와 주소와의 연결방법을 자세히 살펴본다.
간단히 비주얼 스튜디오의 디버그창을 통해 변수의 메모리주소를 확인해 보았다.
위의 inum은 변수가 초기화되기전의 쓰레기값이다. 그리고 그 밑의 &inum은 inum의 메모리 주소를 16진수로 표시한 것이다. 비주얼 스튜디오의 뷰텝에 메모리를 직접 보여주는 기능도있다.
위에서 선언한 inum의 주소 0012FF7C를 검색해서 들어가보면 메모리 값을 읽을 수 있다. 위 사진은 inum에 숫자 3을 넣고 그 메모리값을 읽은 사진이다. 사진을 보면 맨 앞에 3이 들어가있는것을 볼 수 있다. 이는 인텔이 리틀엔디언을 사용하기 때문. 하지만 1바이트 자체가 뒤집히지는 않는다. 예를 들면 12 34 56 78을 저장한다면 메모리에는 78 56 34 12 이런 순으로 들어간다는 뜻.
위 메모리 사진의 오른쪽에는 xV4.이 찍혀있다. x는 앞의 78의 아스키 코드를 이야기하는것이고 .은 제어문자이다. 인텔이 사용하는 리틀엔디언은 계산이 빠르다는 장점이 있다.(빅엔디언은 대소비교가 빠르다.)
위 사진은 여러개의 변수를 선언한뒤 저장된 모습을 본 것이다. 가장 먼저 선언한 n1이 가장 높은 메모리 주소에 저장된 것을 볼 수 있다. 이렇게 되는 이유는 스텍(stack)에 대해 알아야 이해를 할 수 있다.
다음은 printf를 사용해 변수의 메모리 주소를 본 것이다. 08x와 p는 사실상 같은 형식으로 출력한다. 08x를 사용할때 0을 입력해주지 않으면 앞의 0이 그냥 빈칸으로 대체된다. 이러면 더 알아보기 어려울 수 있으므로 0을 넣어주는것이 좋다.
다음은 포인터 사용에 관한 간단한 예제다.
printf를 통해 첫번째 줄에는 변수 x의 주소를 나타내고 있다. 두번째 줄은 변수 x의 값을 이야기하고, 세번째 줄은 포인터 변수인 xp의 주소를 나타내고 있다. 그리고 네번째 줄은 포인터변수 xp가 담고 있는 값을 나타내고있다. 마지막줄은 포인터변수 xp가 가리키고 있는 곳의 값, 즉 x의 값을 나타내고있다.
위는 비쥬얼스튜디오의 디버깅을 이용해 어떻게 들어가있는지 확인한 사진이고, 아래는 위 예제에 대한 심볼테이블이다.
자료형을 선언할때 *를 쓰게되면 그 자료형은 포인터형이라 한다. x는 인트형이고 xp는 포인터형이되는것이다. 포인터는 기본적으로 unsigned int형이다.(주소는 양의 정수밖에 없다.)
*는 두가지로 연산된다. 하나는 *에 다항이 쓰였을때 곱셈기호로 사용된다. 나머지 하나는 *에 단항이 쓰이면 포인터로 인식되 활용된다. 포인터 *를 쓰려면 변수 선언시에 반드시 * 를 붙여 놓아야 한다(ex : int *xp;) *를 두개 이상 붙일 수도있다.(ex : int ***xp;) 두개 이상 붙여 선언했을시 xp 는 xp, *xp , **xp , ***xp 이렇게 4가지로 사용 가능하다. 포인터는 직접 변수를 수정할 수 없다. 다만 주소를 이용해 간접적으로 변수를 수정 가능하다. 이를 간접자료수정이라 한다. *형 앞에 있는 형 지정자는 포인터가 가리키고 잆는 값의 타입을 따라간다고 한다. 즉 int형 값을 가리키고 있는 포인터는 마찬가지로 int형이 되는것이 좋다. 주소값을 바로 주소로 활용하기 위해서는 예를 들면 100이 주소값이라 하면 100에 3을 넣는다고 할떄 100 = 3;에서 100을 주소값으로 바꿔주려면 캐스트 연산을 써주면된다(ex *((int *)100)=3;)
위 그림과 같은 형식으로 코딩하면 0x0012FF7C가 주소값으로 사용된다(사진에서는 00이 생략됨) *포인터형은 short로 선언해도 4바이트다(4바이트주소체계면)
다음 예제를 보자.
int형으로 변수를 선언하고 int형 포인터, short형 포인터 char형 포인터, float형 포인터로 각각 inum을 가리키게 했다. 그리고 각각 받은 값을 출력시켰다. 모든 포인터는 기본적으로 4바이트지만 포인터형 앞에 지정된 형 지정자에 따라 다르게 표시한다.
float는 저장하는 방식이 정수형과 완전히 다르기 때문에 제대로 나오지 않는다. float형은 제쳐두고 나머지 형에 대해 확실히 알아야 할 것은 short *로 선언이되면 *이 가리키고 있는곳의 값을 short형으로 해석하라 라는 뜻이라는거다. 하지만 이렇게 컴파일 하게되면 컴파일러는 Warning을 띄운다. short *sp = &inum의 자료형이 맞지않다고 경고한다.(C ++에서는 아예 error를 뿜는다) 이를 수정하기 위해서는 캐스트연산자를 사용해 자료형을 캐스팅 해주어야 한다. (ex : short *sp = (int *)&inum; ) 하지만 캐스팅을 해주나 해주지 않으나 나오는 어셈블러는 완전히 똑같다. 실행속도도 똑같다. 단지 Warning을 없애기 위해 캐스팅을 하는것이지만 될수있으면 해주는게 좋다.
'12년 내장형하드웨어 김효중입니다. 열심히 하겠습니다.
'코스웨어 > 12년 내장형하드웨어' 카테고리의 다른 글
유용한 프로그램들 (0) | 2012.07.19 |
---|---|
2차배열의 주소와 값 (0) | 2012.07.18 |
보수 (0) | 2012.07.18 |
ARM보드 프로그램 설치/파일넣기 (0) | 2012.07.18 |
ARM (0) | 2012.07.18 |
2012. 07.17 일자 API 수업 정리자료 입니다. (과제 포함) (0) | 2012.07.18 |
문자열 함수 정리 (0) | 2012.07.18 |
소스 인사이트 단축키 및 한글입력팁 (1) | 2012.07.18 |