YUIN

자료구조 1 [배열, 포인터, 문자열, 동적메모리할당] 본문

자료구조

자료구조 1 [배열, 포인터, 문자열, 동적메모리할당]

유_인 2023. 7. 31. 16:54

 

1. 메모리

 

-컴퓨터의 메모리는 데이터를 보관하는 장소

-바이트 (8bits) 단위로 주소가 지정된다

-모든 변수는 주소를 가진다

 

2. 포인터

 

-포인터는 메모리 주소를 값으로 가지는 변수이며, 다음과 같이 선언된다.

type_name * variable_name

-variable_name은 선언된 포인터 변수의 이름이며 *는 variable_name이 포인터 변수임을 표시하고, type_name은 포인터 변수 variable_name에 지정될 주소에 저장될 데이터의 유형을 지정한다

int * ptr

 

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

int c=12;

int * p;

p=&c;  // 포인터 변수 p에 변수 c의 주소를 저장한다

 

-예제 1

#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 sum, i;
	sum = 0;
	for (i = 0; i < 10; i++)
		sum = sum + array[i];
	return sum;
}

* 변수를 매개변수로 받을 때 int array[] 대신 이렇게 포인터로 받을 수도 있다.

 

3. 포인터 arithmetic

 

-*a와 a[0]은 동일한 의미이다. //a의 주소값은 a에 할당된 메모리 중 가장 앞 칸을 의미하는 것이기 때문

-또한 a[1]은 *(a+1)과 동일하고, a[i]는 *(a+i)와 동일하다.  //이러한 연산을 포인터 arthimetic이라고 부른다.

 

포인터 arithmetic에 의하여 

#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 sum, i;
	sum = 0;
	for (i = 0; i < 10; i++)
		sum = sum + *(array+i); //instead of array[i]
	return sum;
}

위 코드는 예제 1 코드와 동치임이 성립된다

 

4. 동적메모리 할당

 

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

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

int *p;
p=(int *)malloc(40); //malloc이 반환하는 주소는 타입이 없는 주소(void*)이다. 정수들을 저장하기 위해서 이것을 int*로 변환한다. 반드시 필요한 건 아니다. 할당받을 메모리의 크기를 byte단위로 지정한다. 여기서는 10개의 정수를 저장하기 위해서 40바이트를 요청하였다. 
if (p==NULL){
/*동적 메모리 할당이 실패
적절한 조취를 취한다*/
}

p[0]=12; //malloc으로 할당받은 메모리는 이렇게 보통의 배열처럼 사용한다
p[1]=24;
*(p+2)=36;

 

5. malloc(memory allocation) 함수

 

- malloc 함수를 이용해서 동적 메모리 할당을 하게 되면 heap 영역에 메모리를 할당받게 된다. 

- malloc 함수는 void 포인터형 함수이며 매개변수로는 양의 정수가 들어간다.

- 반환값은 void 포인터형이며 매개변수는 할당할 메모리의 크기이다.

     ptr =malloc(int_byte)

- 동적 메모리 할당에 성공하면 메모리 주소값을 반환한다

- 실패한다면 NULL값이 반환된다.

 

6. 배열 키우기

 

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

 

for문을 사용하여 array 변수에 있던 데이터를 옮겨준다

int * array = (int *) malloc (4*sizeof(int));
//배열 array의 크기가 부족한 상황이 발생한다
int *tmp=(int*)malloc(8*sizeof(int));
int i;
for(i=0;i<4;i++)
	tmp[i]=array[i];
array=tmp;

 

7. 배열(array)과 malloc 함수

 

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

int a[10];

위와 같은 코드가 있다고 했을 때, 10개의 정수를 수용할 수 있는 메모리 (40바이트= 정수(4) * 10개)가 할당된다. 

 

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;

실제로 위 코드를 visual studio code에 입력하면 array=tmp; 줄에서 array에 오류가 생기는데,

이는 array를 포인터 변수로 선언했을 때는 array는 하나의 변수이므로 그 값을 얼마든지 수정할 수 있지만 배열로 선언하게 되면 array의 값은 수정할 수 없는 값이 되므로 오류가 생기게 되는 것이다.