Language/C

[C언어] 자료구조를 위한 기초 문법 리뷰 - 포인터, 배열, 동적 할당

Jonnie 2021. 2. 15. 23:00

포인터(Pointer)란?

메모리 주소를 값으로 가지는 변수

 

 

포인터 변수의 선언

 

타입명 * 변수명;

 

* : 뒤에 오는 변수가 포인터임을 알려주는 기호

 

ex. int * ptr;

▷ ptr은 포인터 변수이기 때문에 메모리 주소를 저장한다. 그 메모리 주소에 저장되는 타입이 int 타입이다.

 

 

연산자 &

변수로부터 그 변수의 주소를 추출하는 연산자

ex)

int c = 5;     //정수형 변수 c는 12의 값을 가진다

int *ptr;          //ptr은 정수형 포인터 변수이다

ptr = &c;       //ptr에는 c의 주소값이 저장된다

 

 

Q. 주소는 왜 4씩 차이 날까?

A. 변수를 int형으로 설정했기 때문에 하나의 변수 당 4 byte씩 공간을 차지하게 되기 때문이다.

 

 

 

포인터 변수 치환

 

int x=1, y=2; int * p; p=&x;

 

 

int x = 1, y = 2;

int * p;

p = &x;

 

 

 

y = *p;

 

y = *p;

 

▷ *가 변수를 선언 할 때는 포인터 변수라는 것을 알려주기 위한 기호

▷ 선언 이외에 사용될 때는 뒤에 오는 포인터 변수가 저장하고 있는 주소의 저장된 값 또는 그 주소가 참조하는 자리를 의미한다

 

위 상황에서는 선언이 끝난 후 치환이 이루어지는 상황으로 후자의 경우에 속한다. 따라서 y는 포인터 변수 p가 저장하고 있는 주소인 x의 값을 가지게 된다.

*p = 0;

 

 

 

*p = 0;

 

포인터 변수가 가리키는 자리의 값에 0을 쓰라는 의미이다

따라서, 메모리 1000번지에 0을 쓰라는 의미로 x = 0이 된다.

 

 

 

 

 

배열

 

배열의 이름 = 배열의 시작 주소(첫 번째 주소)를 저장하는 포인터 변수 (단, 그 값을 변경할 수 없다)

*a와 a[0]은 동일한 의미

 a[1]은 *(a+1)과 동일하고, a[i]는 *(a+i)와 동일하다

 

포인터 arithmetic: 포인터 변수에 더하기 연산을 하는 것

하나의 정수가 4byte로 표현되는 경우, +1을 한다는 것의 의미는 4를 더해준다는 의미가 된다.

즉, 그 다음 정수의 주소가 되도록 (1000 → 1004) 한다.

ex. *(a+1)

 

+plus)

char  1byte

int 4byte

long long  8byte

 

 

동적 메모리 할당 (Dynamic Memory Allocation)

 

일반적으로 데이터를 저장하기 위한 메모리 공간이 필요하면 변수를 선언해서 그 변수에 데이터를 저장하는 것이 가장 일반적인 방식이다.

 malloc 함수를 호출하여 동적 메모리 할당을 요청 요구한 크기의 메모리를 할당 해당 메모리의 시작 주소 반환

 

int * p;
//malloc으로 주소를 받아올 건데 그것을 사용하려면 주소를 보관해둘 곳이 필요하므로 변수에 대입.주소이므로 포인터 사용

p = (int *)malloc(40);
//int의 사이즈가 4라고 가정하고 계산하여 malloc하는 것보다는 10*sizeof(int)가 더 바람직
//malloc이 반환하는 주소는 타입이 없는 주소(void *) 정수들을 저장하기 위해 int *로 변환함 (필수X)

if (p==NULL) {
	/* 동적 메모리 할당이 실패 */
    /* 적절한 조치를 취한다. */
}

//malloc으로 할당받은 메모리는 배열처럼 사용 가능하다
p[0] = 12;
p[1] = 24;
*(p+2) = 36;	//*(p+2)==p[2]
...

 

언제 배열 대신 동적할당을 사용할까?

배열은 크기가 고정되어 있으므로 공간 부족에 대한 문제 해결이 어렵다.

동적으로 할당된 배열은 공간이 부족할 경우 더 큰 배열을 할당하여 사용 가능하다.

 

int * array = (int *)malloc(4*sizeof(int));
array[0] = 1;
array[1] = 2;
*(array+2) = 3;

int * tmp = (int *)malloc(8*sizeof(int));
int i;
for (i=0; i<4; i++)
	tmp[i] = array[i];	//원래 배열에 있던 모든 데이터를 새로 할당 받은 배열에 복사
  
 array = tmp;
 //array, tmp 모두 포인터 변수. tmp가 가지고 있는 값(32byte 메모리 공간의 주소)을 array에 저장
 //기존 array가 가지고 있던 주소에 위치한 배열은 garbage가 됨

 

위 코드에서 int * array = (int *)malloc(4*sizeof(int)); 를 int array[4];로 바꿔도 되지 않을까?

▷ 배열은 시작 주소를 변경할 수 없다

따라서, int array[4];를 사용할 경우, array = tmp; 에서 오류가 나는 것을 확인할 수 있다.

 

 

 

*참고 강의. 'C로 배우는 자료구조 및 여러가지 예제 실습' - 권오흠


* 잘못된 내용에 대해서는 댓글 남겨주시면 확인 후 수정하겠습니다

 

 

'Language > C' 카테고리의 다른 글

[C언어] 자료구조를 위한 기초 문법 리뷰 - 문자열  (0) 2021.02.17