포인터 - 포인터 변수가 가리키는 자료형의 의미, 세그먼테이션(segmentation)
복습
100번지 |
101 |
102 |
103 |
104 |
105 |
106 |
74 |
56 |
AB |
64 |
12 |
70 |
82 |
int A=103;
char *p;
printf("%d\n",*p); // p의 주소가 103번지라면
⇒ 출력은 100, 64를 십진수 정수형으로 출력한 값이 나온다.
printf("%d\n",p);
⇒ 103이 출력된다. p는 unsigned int 형이다.
symbol table
type |
name |
|
int char * |
A P |
|
printf("%d\n",A);
⇒ 에러, *는 다항일 때 곱셈이고, 단항일 때 포인터이다.(포인터는 주소값을 따라간 메모리의 값)
포인터 선언 안 된 변수 A에 *는 곱셈으로 인식되어 다항(좌 * 우) 연산자가 되어야 하므로 좌 항이 없는 위 명령문은 에러
⇒ 에러를 확인할 때 심벌 테이블의 좌우가 맞는지를 확인해 보아야 한다.
⇒ p=103; 이라고 선언하면 경고가 뜬다. 출력이 되기는 하지만 p는 char형이고 103은 int 형이므로 좌우의 형이 다르다. 따라서
p=(char *) 103;
// short 형의 포인터 변수가 int 형의 데이터를 접근하는 프로그램
#include<stdio.h>
int main()
{
int iNum;
int *ip; // ip는 int 형을 가리키는 포인터 변수
short *sp; //sp는 short 형을 가리키는 포인터 변수
iNum=0x0F5A0B43; // iNum 초기화
ip=&iNum; //ip의 초기화
printf("iNum: %08X ip : %08X\n", iNum, ip);
sp = (short *)ip; // sp가 iNum을 가리킨다.
printf("sp: %08X, *sp: %X\n",sp,*sp);
sp++; // sp가 iNum의 세 번째 바이트를 기리킨다.
printf("sp: %08X, *sp: %X\n", sp, *sp);
return 0;
}
⇒ 실행결과
⇒ sp = (short *)ip;
→ sp는 short형이고 ip는 int 형이므로 좌우의 크기를 맞추어주기 위해 캐스팅을 하였다.(unsigned short *)
⇒
type |
name |
메모리 값 |
비고 | ||||||||
int |
iNum |
|
메모리에 Little Endian으로 저장된다. 즉, 화면표시와는 반대 | ||||||||
ip = &iNum; | |||||||||||
int * |
ip |
|
| ||||||||
sp = (short *)ip; | |||||||||||
short * |
sp |
|
|
→ 타입을 보면 iNum은 int형 이므로 4byte, 뒤에 ip와 sp는 포인터 형이므로 4byte 이다.
⇒ sp = sp+1;
→ 여기서 1은 type * 1과 같다.(자료형의 크기만큼 더해진다.) 즉 short 형인 sp에 1을 더한다는 것은 2byte를 더한다는 것이므로 주소값이 2byte 만큼 더해진다.
⇒ 포인터 변수가 다른 자료형의 변수를 가리키면 프로그램의 오류를 발생시킨다.
⇒ 일반 변수와 마찬가지로 포인터 변수도 항상 값을 초기화해 주고 난 다음 사용해야 한다. 포인터 변수의 초기화는 포인터 변수가 가리키는 메모리를 지정하는 것이다. 초기화 되지 않은 포인터 변수는 세그먼테이션 오류를 발생시킬 수 있다.
※ 세그먼테이션 오류
→ 포인터가 초기화 되지 않아 문제가 된다. 즉, 초기화 되지 않은 포인터는 OS 영역 등 중요한 주소에 접근해 버릴 수 도 있다. 예전 윈도우 95와 98 등에서 자주 일어났던 블루스크린은 사용하는 프로그램이 OS 영역을 건드려서 발생했다. 최신 버전의 윈도우에서는 윈도우가 OS 시스템을 잘못 건드리게 되는 응용 프로그램의 동작이 있다면 해당 프로그램을 정지시킨다.
세그먼테이션(segmentation)에 대한 간단한 조사
- 가상 메모리에서 실제 물리 메모리까지
Windows 운영체제에서 프로그램이 접근하는 메모리는 가상 메모리이며 이 가상 메모리가 실제 물리적 메모리로부터 읽혀지거나 쓰여지게 되는 과정은 인텔 80x86 프로세서에서 지원하는 세그먼테이션 과정과 페이징 과정에 의해서이다.
Windows 운영체제에서 사용자가 지정한 메모리 주소와 세그먼트 레지스터가 합해져서 얻어지는 메모리를 선형 메모리(Linear Address)라 부르며, 사용자가 지정한 메모리 주소로부터 선형 메모리까지 얻어지는 과정을 세그먼테이션(Segmentation)이라 부른다.
세그먼테이션 과정에서는 접근하고자 하는 메모리에 대한 여러 가지 보호 검사가 수행되어지게 되며, 이러한 보호에 의하여 권한이 낮은 프로그래밍 시스템의 중요 메모리 영역을 망가뜨리지 못하게 할 수 있게 된다.
접근하고자 하는 메모리에 대한 세그먼테이션 과정이 끝나게 되면 마이크로프로세서는 위 과정에서 얻어진 선형 메모리(Linear Address)로부터 인텔 80x86의 페이징 메커니즘에 의하여 실제 물리적 메모리의 주소를 얻어오게 되며, 이 과정에서 실제로 이전에 배웠던 페이징 과정이 일어나게 되는 것이다.
- 세그먼트 레지스터와 그 사용
80386이 출현하여 모든 레지스터가 32비트로 바뀐 이후에도 세그먼트 레지스터의 조합개념은 동일하게 적용되어졌다.
프로세서가 메모리에 접근하고자 할 때에는 언제나 세그먼트 레지스터와 조합을 이루며 사용되어졌다.
단지, 기존의 부족한 레지스터의 사이즈를 채우기 위한 용도가 아닌 메모리에 대한 여러 가지 보호를 하기 위한 목적으로 사용되어지게 되었다.
→ 해당 세그먼트에 접근 가능한 메모리 범위
→ 해당 세그먼트를 사용하는 프로그램의 특별한 권한 등의 부여
→ 이를 통해 시스템을 보다 안정적이고 보안적 신뢰가 가능한 시스템을 구성할 수 있도록 하는데 사용됨.
[참조]
윈도우 구조와 원리 - 세그먼테이션(http://blog.daum.net/peinsiro/6634287)
'내장형 하드웨어 > C언어' 카테고리의 다른 글
컴파일 5단계, 분할 컴파일, linux 기본 명령어 복수 (0) | 2011.04.20 |
---|---|
포인터 - CPU와 BUS MEMORY간 전송과정, void, return, 함수 (0) | 2011.04.19 |
포인터 변수의 변화, 주소 저장 방식 - Big Endian, little Endian (1) | 2011.04.15 |
무한반복문, break, 포인터 (0) | 2011.04.14 |
for문 (초기식과 증감식의 변형, 무한반복문) (0) | 2011.04.13 |