[열혈C프로그래밍] chapter 11. 포인터의 이해

chapter 11

포인터의 이해

포인터(변수)란?

=> 포인터 변수란 메모리의 주소값을 저장하기 위한 변수이다.

int main(void){
  char ch1='A', ch2 = 'B';
  char *ptr1 = &ch1, char *ptr2 = &ch2;
  /*
  포인터 변수 ptr1은 변수 ch1의 주소값을 저장하기 위한 변수.
  포인터 변수 ptr2은 변수 ch2의 주소값을 저장하기 위한 변수.
    */
}

=> ptr1, ptr2 : 포인터 변수의 이름 char *:char형 변수의 주소값을 저장하는 포인터 변수의 선언

포인터와 관련 있는 연산자: & 과 *

int num=2;
int* pnum =#

포인터 변수의 크기

=> 포인터 변수는 주소값들을 모두 표현하기 때문에 cpu의 주소체계에 따라 크기가 달라져야 한다.
따라서 16bit cpu에선 포인터의 크기가 2byte, 32bit cpu에선 포인터의 크기가 4byte, 64bit cpu에선 포인터의 크기가 8byte이다.

다양한 ‘포인터 형(type)’이 존재하는 이유

: 포인터의 형(type)은 메모리 공간을 참조하는 기준이 되므로, 변수의 자료형에 맞게 포인터 형(type)을 맞춰야 한다. int -> int*, char -> char*

int main(void){
  double num =3.14; //자료형이 double인 num
  int *pnum = #// pnum은 int 형이므로 double인 num의 주소값을 제대로 저장할 수 없다. 
  printf("%d" , *pnum);
  //num은 double(크기:8byte)인데 , pnum은 int라 num을 4바이트에 정수로 해석하여 저장하게 되는데
  //이러면 num이 얼마가 출력될 지 알 수 없고 의미도 없다.
}

=> 다시 말해 , 포인터의 형의 존재 이유는 포인터 기반의 메모리 접근 기준을 마련하기 위함이다.
변수의 자료형에 잘 맞게 포인터 형을 작성하자.

잘못된 포인터의 사용과 널 포인터

int main(void){
  int *ptr; // 포인터 변수를 선언만 하고 초기화하지 않으면 쓰레기 값이 되어버려 주소값이 어디로 튈지 모른다. 
  *ptr =200 // 주소값도 정확히 모르면서 *연산자를 통해 메모리 참조를 해선 안된다.
  // 왜냐하면 ptr이 참조한 주소가 컴퓨터의 중요 시스템의 정보값의 주소라면, 
  //컴퓨터의 중요 값을 변화시켜 치명적인 오류를 범할 수 있기 때문이다.
}

포인터 변수를 선언만 하고 나중에 초기화 하고 싶을 경우

int main(void){
  int *ptr1 =0; //0은 널포인터를 의미한다.
  int *ptr2 =NULL;//NULL은 널포인터를 의미한다.

  return 0;
}

=>위의 코드와 같이 우선 NULL로 주소값을 채운다. null로 할당하면 주소값을 아무데도 가리키지 않으므로
메모리 공간에 아무런 영향도 미치지않기 때문에 후에 적절한 주소값을 할당하고 싶다면 이렇게 해결할 수 있다.
여기서 NULL은 널포인터라고 얘기한다.