Chapter 8. 포인터(Pointer)
1. 포인터
- 포인터
· 다른 변수의 주소를 저장하는 변수
· 포인터 또한 변수이기 때문에 포인터 변수라고도 한다.
· 포인터 변수의 크기
◦ 포인터 변수의 크기는 시스템의 주소 값 크기에 따라 달라진다.
◦ 16bit 시스템 : 주소값 크기가 16bit이기 때문에 포인터 변수의 크기가 16bit(2byte)가 된다.
◦ 32bit 시스템 : 주소값 크기가 32bit이기 때문에 포인터 변수의 크기가 32bit(4byte)가 된다.
- & 연산자
· 변수의 주소를 구할 수 있게 해주는 연산자
· 배열의 주소를 &연산자를 이용해 구하면 배열의 요소 중 가장 앞의 변수인 0번 변수의 주소를 구해준다.
· scanf 함수에서 &를 사용하는 이유
◦ scanf 함수 또한 함수이기 때문에 함수외부의 변수에 접근하기 위해서는 주소값이 필요하다.
◦ 문자열을 %s와 문자 배열의 이름을 이용해 출력하는 이유 또한 배열의 이름이 주소값을 의미하기 때문이다.
- 포인터의 선언
int* pnum; |
· 포인터를 선언할 때는 주소값을 구하고자하는 변수와 같은 데이터형에 *을 붙여주면된다.
· *의 위치는 데이터형과 변수명 사이에만 써주면 된다.
· 포인터는 시스템의 주소값 크기에 따라 2byte 또는 4byte가 된다.
- * 연산자
연산자 |
형식 |
용도 |
예 |
* |
변수, 상수 |
곱하기 |
a*b; |
데이터형 * 변수명 |
포인터(주소를 저장하는 변수) |
int * p; | |
*포인터명 |
간접접근(포인터가 가리키는 값) |
*p; |
· *연산자는 위치에 따라 용도가 3가지가 있다.
· 간접접근 : *연산자와 포인터를 이용한 메모리 접근방식
· 포인터는 간접접근을 하기 위해 데이터형이 필요하고 각 데이터형에 해당하는 변수에만 접근할 수 있다.
- 포인터의 잘못된 사용
int *ptr; |
· 위처럼 포인터변수를 어떠한 변수를 가리키지도 않은 상태에서 값을 집어넣으면 포인터 변수는 쓰레기 값으로 초기화되며 값이 저장되는 위치를 알 수가 없게 되어 포인터가 잘못 사용 됐음을 알 수 있다.
- 널포인터
int *ptr = 0; |
· 잘못된 포인터 연산을 막기 위해 특정한 값으로 초기화하지 않는 경우 아무것도 가리키지 않겠다는 의미로 null 또는 0으로 초기화를 한다.
2. 배열과 포인터
- 배열이름의 의미
· 배열의 이름은 배열의 시작 주소값을 의미하는 포인터이다.
· 단순히 주소 값이 아닌 포인터인 이유는 *연산자 없이도 메모리 접근에 사용되는 *연산이 가능하기 때문이다.
· 배열의 주소값은 배열의 첫 번째 요소의 주소값과 같다.
- 배열이름과 포인터변수
비교 |
배열 |
포인터 변수 |
이름 |
존재 |
존재 |
저장되는 것 |
메모리의 주소값 |
메모리의 주소값 |
주소값 변경 |
가능 |
불가능 |
- 배열의 포인터 연산
int arr[3] = {1,2,3}; |
· 배열은 각 인덱스끼리 주소값이 1씩 차이가나며 만약 *연산자를 이용해 *(배열명+1) 하면 주소값에 1을 더한 배열의 인덱스를 찾아간다. 즉, +1을 하면 두 번째 요소를 찾아간다.
· 만약 *(배열명+1)에서 괄호를 뺀다면(*배열명+1) *연산자를 먼저 연산해 배열의 첫 번째 인덱스 값에 +1을 한 값을 보여줄 것이다.
3. 문자열과 포인터
- 문자열 리터럴
char* p="abcde"; |
· 문자열 리터럴은 문자열 리터럴의 주소를 의미한다..
· 포인터 변수를 문자열로 초기화하면 문자열 리터럴이 되는데 이는 포인터 변수에 문자열이 저장되는 것이 아니고 메모리상에서 어떤 자리를 문자열이 차지하게 되고 그 자리의 주소가 포인터 변수에 저장이 된다.
· 포인터 변수는 상수가 아니므로 다른 문자열로 초기화하면 다른 주소가 저장된다.
- const 포인터
const char* p |
· const가 데이터형 앞에 위치한 경우
◦ 포인터가 가리키는 것 : 변경 불가능
◦ 주소 : 변경가능
· const가 데이터형과 변수명 사이에 위치한 경우
◦ 포인터가 가리키는 것 : 변경가능
◦ 주소 : 변경 불가능
· const가 데이터형 앞과 데이터형과 변수명 사이 두 곳에 위치한 경우
◦ 포인터가 가리키는 것 : 변경 불가능
◦ 주소 : 변경 불가능
4. 포인터의 연산
int * ip = 0x0010; |
double * dp = 0x0010; double * p; p = dp+1; |
- 포인터는 주소값이며 주소값에 +1과 같은 값을 더해주는 연산을 한다면 해당 포인터 변수의 메모리 크기만큼 주소값을 더해준다.
즉, int 포인터형은 4byte, double 포인터형은 8byte씩 증가하기 된다.
- 주소값
· 변수의 주소값은 실제로 선언할 때마다 점점 감소하는데 이는 메모리상에서 변수가 선언될 때마다 뒤에서부터 메모리가 할당되기 때문이다.
· 반면에 배열의 인덱스별 주소값은 점점 증가하며 메모리상에서 하나의 배열은 배열의 첫 번째 인덱스부터 끝 인덱스까지 모두 한 번에 할당되기 때문에 인덱스 번호가 커질수록 주소값도 커진다.
· 주소값의 예
|
5. 포인터와 함수
- 함수의 데이터 전달 방법
· Call-by-Value
◦ 값에 의한 전달방법으로 함수를 단순히 값을 전달하는 형태의 함수로 호출하는 것
◦ 함수 외부의 선언된 변수에 접근이 불가능하다.
◦ 함수 외부의 선언된 변수에 접근이 불가능하기 때문에 함수의 연산결과를 변수에 저장해야 함수 외부에서 결과를 볼 수 있다.
· Call-by-Reference
◦ 주소에 의한 전달방법으로 함수를 메모리 접근에 사용되는 주소 값을 전달하는 형태의 함수로 호출하는 것
◦ 함수 외부의 선언된 변수에 접근이 가능하다.
◦ 함수 외부의 선언된 변수에 접근이 가능하기 때문에 함수를 통해 연산만 해주면 된다.
'C Langauage' 카테고리의 다른 글
Chapter 10. 전처리기(Preprocessor) (0) | 2015.08.05 |
---|---|
Chapter 9. 문자열(String) (0) | 2015.08.05 |
Chapter 7. 함수(Function) (0) | 2015.08.05 |
Chapter 6. 배열(Array)과 문자열(String) (0) | 2015.08.05 |
Chapter 5. 제어문 (0) | 2015.08.05 |