void형변수, 동적메모리할당

·2023년 3월 11일
0

C

목록 보기
9/13

📌리턴값이 없는 함수


리턴 할 필요가 없는 함수에 사용된다.
리턴형을 void로 설정


📌void형 포인터 변수


int main()
{
	//void a;	//메모리상에 얼마만큼의 공간을 줘야하는지 모름
	void* b; //포인트라서 메모리상에 64비트 기준 8바이트 할당됨(오직 주소값만 할당)
	double c = 123.3;

	//a = 3; 오류발생
	b = &c;

	printf("%lf", *(double*)b);	//void 포인터의 주소값은 double 포인터의 주소값으로 형변환
	

	return 0;
}

b가 가르키는 주소형은 double형 변수의 주소값이라 생각한다.

#include <stdio.h>

int main()
{
	int arr[1] = { 0x12345678};

	printf("%x \n", arr[0]);
	read_char(arr, 4);
	return 0;
}
int read_char(void* p, int byte)
{
	do {
		printf("%x \n", *(char*)p);
		byte--;

		p = (char*)p + 1;
	} while (p && byte);

	return 0;
}

78부터 나오는건 리틀엔디안 방식으로 작동하기 때문이다. arr를 받아올때 void형식으로 받아와서 char포인터 형식으로 +1을 해주면 주소가 하나씩 증가한다.


📌메인함수의 인자


#include <stdio.h>

int main(int argc, char **argv)
{
	printf("받은 인자의 개수 : %d \n", argc); //main 함수가 받은 인자의 수(기본적으로 운영체제가 넣어줌)
	printf("이 프로그램의 경로 : %s \n", argv[0]);	//main 함수가 받은 받은 인자들

	return 0;
}

cmd창을 키고 실행 시켜야 제대로된 결과를 볼수가 있다.


📌동적메모리 할당


배열을 정할 때 그 크기는 언제나 컴파일 시간에 확정되어야 한다.
이렇게 되면 쓸데없이 큰 수를 넣는 경우가 많아서 낭비가 생긴다 이를 줄이기 위해서 필요한 만큼만 쓸 수 있도록 동적할당을 사용한다.

#include <stdlib.h> //이 라이브러리에 정의되어 있다.

malloc

memory allocation의 약자

arr = (int *)malloc(sizeof(int) * arr_size)

인자로 전달된 크기의 바이트 수 만큼 메모리 공간을 만든다
int형 크기를 알고 싶으면(int의 크기) * (arr_size)를 해주면 된다.
리턴형은 (void*) 형이라서 앞에 (int*) 이런식으로 형변환이 필요하다.

free(arr)

다 쓰고 메모리에 돌려주는 역할
free를 제대로 안하면 메모리 누수가 생긴다.
해제 순서는 할당하는 순서의 반대

int main()
{
	int arr_size;
	int* arr;
	int sum = 0;

	printf("학생의 수는? :");
	scanf("%d", &arr_size);

	arr = (int*)malloc(sizeof(int) * arr_size);

	for (int i = 0; i < arr_size; i++)
	{
		printf("학생 %d 의 점수 : ", i);
		scanf("%d", &arr[i]);
		sum += arr[i];
	}
	printf("전체 학생의 평균 점수 : %d \n", sum / arr_size);
	free(arr);
}

maloc함수는 힙을 사용해서 자유롭게 할당하거나 해제할 수 있다.


📌2차원 배열의 동적할당


2차원 배열 동적할당 2가지 방법
1. 포인터 배열을 사용해서 2차원 배열처럼 동작하는 배열을 만든다.
2. 실제로 2차원 배열 크기의 메모리 할당 뒤 2차원 배열 포인터로 참조한다.

1번 방식으로 구현

int main()
{
	int i;
	int x, y;
	int** arr;

	printf("arr[x][y] 만들기\n");
	scanf("%d %d", &x, &y);

	arr = (int**)malloc(sizeof(int*) * x);

	for (i = 0; i < x; i++)
	{
		arr[i] = (int*)malloc(sizeof(int) * y);
	}

	printf("생성완료!");

	for (i = 0; i < x; i++)
	{
		free(arr[i]);
	}
	free(arr);

	return 0;
}

인자는 int arry(int **arry) 이런식으로 넘겨준다. 만든 배열은 2차원으로 보이긴 하지만 실제론 1차원 배열들이다.

void get_average(int** student_Score, int numSubject, int numStudent);
int main()
{
	int i;
	int subject, student;
	int** student_score;
	printf("과목의 수 : ");
	scanf("%d", &subject);
	printf("학생의 수 : ");
	scanf("%d", &student);

	student_score = (int**)malloc(sizeof(int*) * subject);

	for (int i = 0; i < subject; i++)
	{
		student_score[i] = (int*)malloc(sizeof(int) * student);
	}
	for (int i = 0; i < subject; i++)
	{
		printf("과목 %d 점수 ----------\n", i);
		for (int j = 0; j < student; j++)
		{
			printf("학생 %d 점수 입력 : ", j);
			scanf("%d", &student_score[i][j]);
		}
	}

	get_average(student_score, subject, student);

	for (int i = 0; i < subject; i++)
	{
		free(student_score[i]);
	}

	free(student_score);

	return 0;
}
void get_average(int** student_Score, int numSubject, int numStudent)
{
	int sum = 0;
	for (int i = 0; i < numSubject; i++)
	{
		sum = 0;
		for (int j = 0; j < numStudent; j++)
		{
			sum += student_Score[i][j];
		}
		printf("과목 %d 평균 점수 : %d\n", i, sum / numStudent);
	}
}

get_average에서 이차원배열 넘어가는 모양확인

2번 방식으로 구현

기존 vs컴파일러에 안돌아가기 때문에 clang이라는 컴파일러를 설치하고 설정해줘야한다.
기본 사용법

Print_arr(int width, int(*arr)[width], int height);
int main() {
	int width, height;
	printf("배열 행 크기 : ");
	scanf("%d", &height);
	printf("배열 열 크기 : ");
	scanf("%d", &width);

	int(*arr)[width] = (int(*)[width])malloc(height * width * sizeof(int)); //width에 실제 배열의 열이 들어간 후 정의해야함

	for (int i = 0; i < height; i++) {
		for (int j = 0; j < width; j++) {
			int data;
			scanf("%d", &data);
			arr[i][j] = data;
		}
	}

	Print_arr(width, arr, height); 
	free(arr);
}
Print_arr(int width, int (*arr)[width], int height) //width를 알도록 먼저 적어준다
{
	for (int i = 0; i < height; i++) {
		for (int j = 0; j < width; j++) {
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
}

앞에서 구현한 과목 학생의 성적 입력과 평균을 2번 방식으로 구현

void input_score(int student, int subject, int(*score)[student]);
void avg_score(int student, int subject, int(*score)[student]);
int main()
{
	int subject, student;
	printf("과목의 수를 입력해주세요: ");
	scanf("%d", &subject);
	
	printf("학생의 수를 입력해주세요: ");
	scanf("%d", &student);
	int (*student_score)[student];

	student_score= (int(*)[student])malloc(sizeof(int) * subject * student);
	
	input_score(student, subject, student_score);
	avg_score(student, subject, student_score);

	free(student_score);
	return 0;

}
void input_score(int student, int subject, int(*score)[student])
{
	for (int i = 0; i < subject; i++)
	{
		printf("%d 번째 과목\n", i);
		for (int j = 0; j < student; j++)
		{
			printf("%d 번째 학생의 점수: ", j);
			scanf("%d", &score[i][j]);
		}
	}
}
void avg_score(int student, int subject, int(*score)[student])
{
	int sum = 0;
	for (int i = 0; i < subject; i++)
	{
		sum = 0;
		printf("%d 번째 과목의 평균 :", i);
		for (int j = 0; j < student; j++)
		{
			sum += score[i][j];
		}
		printf("%d\n", sum / student);
	}
}

동적을 할당된 배열의 크기를 다시 바꾸는 프로그램

int main()
{
	int* p;
	int p_size;
	printf("크기를 입력해주세요: ");
	scanf("%d", &p_size);

	p = (int*)malloc(sizeof(int) * p_size);
	
	for (int i = 0; i < p_size; i++)
	{
		p[i] = i;
	}

	add_size(&p, &p_size);

	for (int i = 0; i < p_size; i++)
	{
		printf("%d ", p[i]);
	}
	free(p);
	
	return 0;
}
int add_size(int** p, int *p_size)	//포인터의 값을 바꾸기 위해서는 이중포인터를 사용해야한다
{
	int* p2, add_size;
	printf("늘릴 크기를 입력해주세요: ");
	scanf("%d", &add_size);
	int newsize = *p_size + add_size;

	p2 = (int*)malloc(sizeof(int) * newsize);

	for (int i = 0; i < *p_size; i++)
	{
		p2[i] = (*p)[i];
	}

	for (int i = *p_size; i < newsize; i++)
	{
		p2[i] = i;
	}

	free(*p);

	*p = p2;
	*p_size += add_size;
}

이중포인터의 역할, size를 어떻게 증가시키는지 사용방법 확인

동적할당 생각할점


📌realloc


편하게 바꾸려면 realloc를 사용하면된다.

int main()
{
	int* arr;
	int* arr2;
	int arr_size;
	scanf("%d", &arr_size);

	arr = (int*)malloc(sizeof(int) * arr_size);

	for (int i = 0; i < arr_size; i++)
	{
		arr[i] = i;
		printf("%d ", arr[i]);
	}
	printf("\n");
	
	arr = (int*)realloc(arr, 3 * sizeof(int));

	for (int i = arr_size; i < arr_size + 3; i++)
	{
		arr[i] = i;
		printf("%d ", arr[i]);
	}

	free(arr);
}

📌구조체 포인터 동적할당


struct Something {
	int a, b;
};
int main()
{
	struct Something* arr;
	int size, i;

	scanf("%d", &size);

	arr = (struct Something*)malloc(sizeof(struct Something) * size);

	for (i = 0; i < size; i++)
	{
		printf("arr[%d].a :", i);
		scanf("%d", &arr[i].a);
		printf("arr[%d].b :", i);
		scanf("%d", &arr[i].b);
	}

	for (i = 0; i < size; i++)
	{
		printf("arr[%d].a : %d, arr[%d].b : %d\n", i, arr[i].a, i, arr[i].b);
	}

	free(arr);
}

일반 변수와 똑같이 사용해주면 된다.

문제(동적할당관련)


Problem4.c

참고자료


씹어먹는 C언어

profile
개인공부저장용(하루의 기록)

0개의 댓글