해당 카테고리에 3학년 2학기를 앞두고 여름 방학 맞이 c언어 복습을 기록하려 합니다. 그동안 배운 c언어 개념 정리와 문제 풀이를 통해 알고리즘 수업을 준비하는 과정입니다. 그동안 수강했던 c언어 수업 자료와 윤성우의 열혈 C 프로그래밍의 내용을 포함해 저에게 기록할 가치가 있는 내용이 담겨 있습니다. 지적과 피드백은 저를 발전시키니 언제나 환영입니다.
포인터 변수
포인터는 c언어가 low 레벨 언어의 특성을 지닌다고 얘기하게 만든 장본인이다. 왜냐하면 포인터를 이용하면 메모리에 직접 접근이 가능하기 때문이다.
low 레벨 언어란?
low 레벨 프로그래밍 언어 또는 저급 프로그래밍 언어라고 부른다. 컴퓨터가 이해하기 쉽게 작성된 프로그래밍 언어다.
포인터를 잘 이해하기 위해서는 메모리 공간을 그림으로 그려가면서 공부해야 이해가 잘 된다.
c언어에서는 주소의 시작번지만을 가지고 위치를 표현한다.
자료형의 크기를 알기 때문에 끝이 어딘지는 쉽게 계산이 가능하기 때문이다.
포인터 변수란 메모리의 주소 값을 저장하기 위한 변수다.
'포인터'는 '변수 형태의 포인터'와 '상수 형태의 포인터'를 어우르는 표현이다. 근데 포인터와 관련된 이야기라면 대부분이 포인터 변수의 얘기이므로, 포인터라 하면 우선적으로 포인터 변수를 연상하면 된다.
포인터 변수의 선언
int * pnum;
pnum 포인터 변수의 이름
int * int형 변수의 주소 값을 저장하는 포인터 변수의 선언
pnum = #
& 연산자는 '오른쪽에 등장하는 피연산자의 주소 값을 반환하는 연산자'이다. & 연산의 결과로 변수 num의 주소 값이 반환되며, 이를 포인터 변수 pnum에 저장한다.
포인터 변수 pnum에는 변수 num의 시작번지 주소 값이 저장된다.
"포인터 변수 pnum이 int형 변수 num을 가리킨다."
"가리킨다"는 포인터를 배운 후로 포인터 이해에 도움 되는 워딩이다. 참조한다는 의미로 인식하면 된다. 화살표로 가리키는 그림을 그리면서 포인터 변수를 이해하면 좋다.
포인터 변수는 메모리에서 변수의 위치를 나타내는 주소를 다루는 변수이므로, 그 크기는 일반적으로 CPU에 따라 결정된다. 포인터 변수의 크기가 주소 값의 크기는 동일하다. 32비트 시스템에서는 주소 값을 32비트로 표현하기 때문에 포인터 변수의 크기가 4바이트고, 64비트 시스템에서는 주소 값을 64비트로 표현하기 때문에 포인터 변수의 크기는 8바이트다.
그동안 모든 포인터 변수의 크기는 4바이트라고 알고 있었는데 몇비트 시스템에서의 주소 값인지에 따라 달라지는 거였다.
주소 값은 동일한 시스템에서 그 크기가 동일하며 모두 정수의 형태를 띤다. 4바이트, 8바이트 모두 가능하다.
& 연산자
& 연산자의 피연산자는 변수이어야 하며, 상수는 피연산자가 될 수 없다.
포인터 형
다양한 '포인터 형'이 존재하는 이유는 뭘까?
포인터의 형은 메모리 공간의 참조하는 기준이 된다.
예를 들어 *pnum에서 pnum이 가리키는 메모리 공간에 접근해서 값을 읽을 때, pnum에 저장된 주소를 시작으로 몇 바이트를 읽을지, 읽은 데이터는 정수로 해석해야 하는지 아니면 실수로 해석해야 하는지의 정보가 필요하다.
* 연산자를 통한 메모리 공간의 접근 기준을 마련하기 위해 포인터 형이 정의된 것이다.
"4바이트를 읽어 들여서 이를 정수로 해석한다"로 접근 가능해진다.
잘못된 포인터의 사용과 널 포인터
int main(void)
{
int * ptr;
*ptr = 200;
..
}
이렇게 포인터 변수를 선언만 하고 초기화하지 않으면, 포인터 변수는 쓰레기 값으로 초기화 된다.
어디를 가리킬지 모른다는 뜻이다. ptr이 가리키는 위치가 어딘 줄도 모르고 접근하는 것은 매우 주의할 상황이다.
int main(void)
{
int * ptr = 125;
*ptr = 10;
..
}
포인터 변수를 초기화 한답시고 125를 저장했다. 더 이상한 것이다.
125번지가 어딘 줄도 모르고 포인터 변수를 이 값으로 초기화했다. 쓰레기 값으로 초기화한 것과 비슷하다.
그럼 어떻게?
int main(void)
{
int * ptr1 = 0;
int * ptr2 = NULL;
..
}
만약 포인터 변수를 우선 선언한 후 유효한 주소 값을 채워 넣을 생각이라면, 위와 같이 초기화하면 된다.
키워드 NULL은 상수 0을 의미하고, 이 값으로 초기화한 포인터 변수를 '널 포인터'라 한다.
아무데도 가리키지 않는다.
따라서 이를 이용한 * 연산은 메모리 공간에 어떤 영향도 미치지 않는다.
프로그램이 멈추긴 해도 잘못된 메모리 접근이 일어나진 않는다.
아무튼 나중에 유효한 주소 값을 채운다면, 우선 널 포인터로 초기화하는 것이다.
'Algorithm > C' 카테고리의 다른 글
[c언어 개념] #6 포인터와 함수 (0) | 2022.07.20 |
---|---|
[c언어 개념] #5 포인터와 배열 (포인터 변수, 포인터 상수, 변수 형태의 문자열, 상수 형태의 문자열, 포인터 배열) (0) | 2022.07.20 |
[c언어 문제] #3 난수 배열 정렬, 선택정렬 알고리즘 (0) | 2022.05.17 |
[c언어 문제] #2 사이클 숫자들, 사이클 길이 출력 (0) | 2022.05.04 |
[c언어 문제] #1 피보나치 수열 값 출력 (0) | 2022.05.04 |