포인터(pointer)
: 주소(address)를 저장하는 변수
메모리에는 각 바이트를 구분하기 위한 주소(번지)가 있다.
32비트 플랫폼에서는 주소가 4바이트 크기이므로 포인터 변수의 크기도 4바이트이다.
64비트 플랫폼에서는 주소가 64비트, 위와 같이 8바이트이다.
플랫폼마다 주소 크기, 즉 포인터 변수의 크기는 차이가 있지만, 1byte = 8bits라는 것만 인지하자.
포인터는 다른 변수를 가리키는 변수로, 주소를 통해 다른 변수에 접근할 수 있도록 도와준다.
포인터 선언
----------------------------------------------------------------------------------------------
포인터 변수를 선언할 때는 데이터형과 *를 쓴 뒤 변수명을 적어준다.
형식 데이터형 *변수명
데이터형 *변수명 = 초기값;
EX int *p
double *pd;
int a = 123;
int *pa = &a;
char *pc = NULL;
----------------------------------------------------------------------------------------------
*는 포인터 수식어로, 그 다음에 있는 변수를 포인터로 만들고, 일반적으로 포인터 변수보다는 포인터라는 말을 쓴다.
포인터를 선언할 때 지정하는 데이터형은 포인터가 가리키는 변수의 데이터형
포인터 선언 시, *를 변수 쪽으로 붙여 써주자.
포인터를 한 줄로 선언할 시에 좀더 알아보기 편하다.
(*의 위치는 int* p;
int * p;
int *p; 셋 다 똑같다. 알아보기 좋은 코드가 좋은 코드라 하지않던가, 가독성을 위해 쓴다 생각하자)
포인터도 용도별로 구분해 사용하기에 포인터를 선언할 때 포인터가 가리키는 변수의 데이터형을 명시한다.
예를 들어, int*형은 int형 변수의 주소를 저장하는 포인터형, double*형은 double형 변수의 주소를 저장하는 포인터형이다.
느그형은 호날ㄷ
포인터도 크기를 확인할 때 sizeof연산자를 사용한다.
포인터의 데이터형이 다르더라도 포인터의 크기는 항상 같다.
int나 double, char형 모두 주소값을 저장하기 때문이다.
포인터의 초기화
포인터도 변수이므로 초기화하지 않으면 쓰레기 값이 된다.
포인터에 직접 절대 주소를 대입해서는 안된다.
컴파일에러나 나아가 실행에러가 발생할 수 있다.
변수의 주소를 구할 때는 주소 구하기(address-of) 연산자 &를 통해 주소를 구한다.
포인터 선언 시 아직 어떤 변수의 주소로 초기화할지 알 수 없는 경우가 있다.
포인터도 변수이기 때문에, 초기화하지 않으면 쓰레기 값이 되므로 0으로 초기화하자.
포인터를 0으로 초기화할 때 NULL 매크로를 이용할 수도 있다.
포인터의 사용
주소 구하기 연산자는 & 다음에 나오는 변수의 주소를 구한다.
포인터가 지정하는 변수에 접근하려면 역참조 연산자 *를 사용한다. 포인터 앞에 *를 쓰면 포인터가 가리키는 변수의 값을 읽거나 변경이 가능하다.
역참조 연산자는 간접 참조(indirection) 연산자라고도 한다. => * 이친구 말하는 겁니다.
포인터의 용도
포인터가 필요한 경우?
- 변수의 이름을 직접 사용할 수 없는 경우
- 포인터가 어떤 변수를 가리킬지 모르나 코드를 작성하는 경우
포인터 사용 주의사항
1) 포인터는 초기화하고 사용하는 것이 안전하다
포인터를 선언하는 시점에 아직 어떤 변수를 가리킬지 알 수 없을 때는, 우선 널 포인터로 초기화한다.
ex) int *q = NULL;
2) 포인터의 데이터형과 포인터가 가리키는 변수의 데이터형이 같아야한다
포인터의 데이터형이 포인터가 가리키는 변수의 데이터형과 같아야한다
포인터 때문에 발생하는 실행 에러는 찾기가 쉽지 않으므로, 코드를 방어적으로 작성하는 것이 안전하다.
이까지 한거 함 집고 넘어가기
- 포인터가 어떤 변수도 아직 안 가리킨다는 의미? NULL 포인터
- double형 변수의 주소를 저장할 때 사용하는 포인터형? 우리형 double형
뭔소린지 모르겠다 싶으면 int는 int형, double은 double형, char은 char형으로 쓴다고 생각하면 됩니다.
변수의 데이터형과 포인터의 데이터형이 일치하지 않으면 사용할 수 없습니다.
CONST 포인터
보통은 값을 변경할 수 없는 변수를 선언할 때 const를 사용한다.
포인터에도 const를 선언할 수 있는데, const 지정 위치에 따라 const 포인터의 의미가 달라진다.
데이터형 앞, 변수 이름 앞, 양쪽 모두 쓸 수도 있다.
1) const 데이터형 *변수;
const 포인터를 읽기 전용 포인터라고 한다.
포인터가 가리키는 변수의 값을 읽을 수만 있고 변경할 수는 없기 때문이다.
const 포인터로 가리키는 변수를 변경하려고 하면 컴파일 에러가 발생한다.
포인터가 다른 변수를 가리키게 만들 수는 있다.
읽기 전용 포인터는 선언 시에 널 포인터로 초기화하며, 원하는 시점에 특정 변수의 주소를 저장 및 사용가능하다.
(const 포인터에는 총 3가지가 있는데 이 중에서 제일 많이 사용되는 방법이다)
2) 데이터형* const변수;
const가 변수 이름 앞에 있으면 포인터 자신의 값(포인터에 저장된 주소)을 변경할 수 없다.
주소 변경이 불가능하기 때문에 특정 변수의 전용 포인터가 된다.
이 const포인터로는 다른 변수를 가리킬 수 없다.
ex) int *const p2 = &a; //p2는 a전용 포인터로 a에 접근하는 용도로 사용된다
a전용 포인터가 가리키는 변수의 값은 변경할 수 있다. p2를 통한 역참조로 a를 변경 가능하다.
특정 변수 전용 포인터는 선언 시 초기화 하지 않으면 주소를 저장할 수 없으므로 반드시 초기화하자!.
초기화를 생략해도 컴파일 에러는 발생하지 않기 때문에 주의해야 한다.
ex) *p2 = 100;
3) const 데이터형 *const 변수;
const가 데이터형과 변수 앞에 모두ㅜ 있으면, 읽기 전용 + 특정 변수 전용 포인터가 된다.
위와 같은 케이스는 초기화는 반드시 해야하며, 포인터가 가리키는 변수를 변경할 수 없고 포인터 자신의 값(포인터에 저장된 주소)도 변경할 수 없다.
'Language & Framework & GIT > C' 카테고리의 다른 글
[씨앤씨뿔] C/ 문자열 -1 (0) | 2023.04.11 |
---|---|
[씨앤씨뿔] C/ 포인터 - 2 (0) | 2023.04.08 |
[씨앤씨뿔] C/ 배열 (0) | 2023.04.04 |
[씨앤씨뿔] C/ 함수 (0) | 2023.04.04 |
[씨앤씨뿔] C/ 제어문 (0) | 2023.03.28 |
댓글