본문 바로가기
개발 Tools/C_개념

C언어 자료구조 메모리와 포인터 ( 포인터, 포인터와 배열, 포인터 arithmetic, 동적 메모리 할당, malloc )

by 전컴반 2022. 1. 10.
반응형
메모리

 

메모리란 데이터를 보관하는 장소이다. 1byte( =8bit ) 단위로 주소가 지정된다.

모든 변수는 주소를 가진다. 변수의 시작 주소 번호가 변수의 대표 번지다 

 

저작권침해의사없음

포인터

 

포인터는 메모리 주소를 값으로 가지는 변수이다. 

 

int * ptr; 

int는 ptr이 가리키는 주소의 저장되는 데이터의 타입이 int임을 나타낸다

 

 

저작권침해의사없음

 

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

 

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

y = *ip; // 변수의 선언이 아니라 포인터 변수 앞에 등장하면 이 포인터 변수가 저장하고 있는 주소에 저장된 값을 의미한다.

*ip = 0; // 포인터 변수가 저장하고 있는 주소에 저장된 값에 0을 집어넣는다.

 

아래 2개의 *ip에서 *ip는 이 포인터 변수가 저장하고 있는 값의 주소에 저장된 값을 의미한다.

 

저작권침해의사없음

 

포인터와 배열

 

 

저작권침해의사없음

 

a [0]의 주소가 포인터 변수(배열의 이름) a에 저장된다. 이게 중요하니 기억해야 한다. 아래 예제를 보면 배열의 이름 주소와 배열 첫 번째 주소가 똑같다는 것을 알 수 있다. 

 

#include <stdio.h>
int main(void)
{
	int sum, i, average;
    int num[10];
    for ( i = 0; i < 10; i++)
    	scanf("%d", &num[i]);
    sum = calculate_sum( num );
    average = sum / 10;
    printf("%d\n", average);
    return 0;
}

int calculate_sum( int *array) // int array[] 로 받아도 똑같다
{
	int sum, i;
    sum = 0;
    for ( i = 0; i< 10; i++)
    	sum = sum + array[i]; // array[i] 대신에 *(array+i) 도 가능하다
    return sum;
}

 

포인터 arithmetic

 

*a와 a [0]는 동일한 의미이다. 또한 a [i]은 *(a+i)과 동일하다. 만약 1을 더한다고 하면 진짜 1을 더하는 게 아니라 다음 주소가 되도록 더해준다. 가령 int 라면 4를 더하고 char면 1을 더한다. 이런 연산을 포인터 arithmetic이라 부른다

 

저작권침해의사없음

 

동적 메모리 할당

 

변수를 선언하는 대신 프로그램의 요청으로 메모리를 할당할 수 있다. 이것을 동적 메모리 할당이라 한다

malloc 함수를 호출하여 동정 메모리 할당을 요청하면 요구하는 크기의 메모리를 할당하고 그 시작 주소를 반환한다.

동적 메모리 할당은 배열을 사용하다 부족했을 때 흔히 사용한다.

 

#include <stdilb.h> // 동적메모리 할당을 사용하기 위한 라이브러리

int *p; 
p = (int *)malloc(40);

p[0] = 12;
p[1] = 24;
*(p+2) = 36;
...
...

 

(int *)는 반드시 필요하지 않으나 정수를 저장하기 위해 사용했다. 기본값은 void *이다. 

malloc은 바이트 단위로 40바이트를 요청했다. 즉, 10개의 정수를 저장하기 위해 만들었다. 이렇게 하면 마치 정수형 배열처럼 사용 가능하다.

 

배열이 부족했을 때 사용법은 원래 배열을 새로 만든 더 큰 배열로 다 옮기는 작업을 수행한다. 이때 원래 주소는 garbage 공간이 된다. 

 

int main(void) 
{
    int *array = (int *)malloc(4*sizeof(int)); // int array[4]; 와는 다르다
    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;
}

저작권침해의사없음

 

위에서는 40이라고 숫자로 지정했지만 호환성을 위해 sizeof 연산자를 이용하여 사용하는 것이 좋다. 

 

int array [4]와 다른 점은 포인터로 선언하면 값을 변경할 수 있기 때문에 array = tmp 가 되지만 일반 배열에서는 값을 변경할 수 없기 때문에 변경이 불가하다. 

 

반응형

댓글