2021. 1. 22. 18:52ㆍ프로그래밍 공부/C 공부
포인터 복습
포인터는 가리키는 대상의 메모리 주소를 저장하여 사용할 수 있도록 하는것이다.
void main()
{
int *p;
int data = 3;
p = &data;
printf("Before data : %d", data)//결과값 3
*p = 5;
printf("Use *p data : %d", *data); //결과값 5
}
다차원 포인터
위의 포인터 *p는 1차원 포인터인데, 포인터가 다른 포인터를 가리키도록 만듦으로써 2차원, 3차원...n차원 포인터를 만들 수 있다.
아래는 2차원 포인터 에시다.
int main()
{
int **pp;
int *p;
int data = 3;
pp=&p;
p = &data;
printf("Before data : %d\n", data); //결과값 3
*p=4;
printf("Use *p, data : %d\n", data); //결과값 4
**pp=5;
printf("Use **p, data : %d\n", data); //결과값 5
}
2차원 포인터는 *를 두개 사용함으로써 만들 수 있고, 최종값(**p)에 도달하기 직전 단계에 *p를 거치도록 하였다.
**p에 값을 입력하면, &p를 거쳐, p가 가리키고있는 &data에 도달하는 것이다.
위의 예시에서는 포인터에 정적할당을 이용하였다.
동적 할당으로 포인터에 메모리 공간을 할당하려면 어떻게 해야할까?
#include <stdio.h>
#include <malloc.h>
int main()
{
int **pp;
pp = (int **)malloc(sizeof(int));
*pp = (int *)malloc(sizeof(int));
**pp = 3;
printf("Before data : %d\n", **pp); //결과값 3
}
[ 포인터 변수 = 주소 ] : 포인터 변수가 가리키는 메모리 공간
이 규칙만 지켜지면 동적할당으로도 충분히 포인터에 메모리 공간을 할당할 수 있다.
활용1. 함수를 통한 포인터 동적할당
그러면 굳이 왜 다차원 포인터가 필요한걸까?
main에 선언된 포인터에 공간을 할당하는 함수를 만들때 다차원 포인터가 유용하게 사용될 수 있다.
//실행 오류//
#include <stdio.h>
#include <malloc.h>
int assignM(int *q);
int main()
{
int *p;
assignM(p);
*p = 5;
free(p);
}
int assignM(int *q)
{
q = (int *)malloc(8);
}
이 코드의 목적은 main에 선언된 포인터 p에 8바이트의 메모리 공간을 할당하는 것이지만, 뜻하는 결과가 나오지 않는다.
main에서 assignM을 호출했을때 매개변수는 int *q = p, 즉 포인터 q에 p값을 입력하고, 함수에서 q가 가리키는 메모리를 8바이트로 할당했을 뿐, p에 어떠한 변화도 주지 못한것이다.
그러면 마지막에 *p = q 를 입력하면 해결될까? 그렇지 않다. *p는 assignM 함수 외에 선언된 변수이기 때문에 assignM에서 활용할 수 없다.
이때 활용할 수 있는게 다차원 포인터이다.
p에 메모리를 할당하는게 목적이라면 p를 가리키는 포인터가 있으면 되지 않을까?
//정상 실행//
#include <stdio.h>
#include <malloc.h>
int assignM(int **q);
int main()
{
int *p;
assignM(&p);
*p = 5;
free(p);
}
int assignM(int **q)
{
*q = (int *)malloc(8);
}
assignM 함수가 호출되면, 매개변수는 int **q = &p 를 의미하고
함수 내부에서는 *q 가 가리키는 변수(**q 즉, &p) 에 8바이트의 메모리를 할당한다.
이러한 방법으로 포인터에동적 메모리 공간을 할당하는 함수를 만들때 다차원 포인터가 활용될 수 있다.
활용2. 다차원 배열
20대~40대 직원들의 윗몸일이키기 점수를 입력하는 프로그램일 경우를 생각해보자.
20대 4명, 30대 2명, 40대 3명으로 이루어진 조직은 static하게 값을 고정하여 코딩할 수 있을 것이다.
#include <stdio.h>
int main()
{
unsigned char limit_table[3] = { 4, 2, 3 }; //각연령대별 인원
unsigned char count[3][4] = { 0, }; // 연령대3개 차원 * 최대인원 4명 메모리배정
int age, member, temp, sum;
for (age = 0; age < 3; age++)
{
printf("\n%d0대 연령의 윗몸 일으키기 횟수\n", age + 2);
for (member = 0; member < limit_table[age]; member++)
{
printf("%dth:", member + 1);
scanf("%d", &temp);
count[age][member] = (unsigned char)temp;
}
}
printf("\n\n연령별 평균 윗몸 일으키기 횟수\n");
for (age = 0; age < 3; age++)
{
sum = 0;
printf("%d0대 : ", age + 2);
for (member = 0; member < limit_table[age]; member++)
{
sum = sum + count[age][member];
}
printf("%5.2f\n", (double)sum / limit_table[age]);
}
}
하지만 각 연령별로 인원이 바뀐다면?
limit_table의 값을 반복문과 scanf로 받는다고쳐도 count의 두번째 차원의 값을 어떻게 유연하게 변화시킬 수 있을까?
포인터와 배열을 이용하면 해결할 수 있다.
#include <stdio.h>
#include <malloc.h>
int main()
{
unsigned char limit_table[3] = { 0, }; //연령병 직원수를 0으로 초기화
unsigned char* p[3]; //3개의 요소를 갖는 포인터 선언
int age, member, temp, sum;
for (age = 0; age < 3; age++) {
printf("%d0대 직원수를 입력하세요.", age + 2);
scanf("%d", &temp); //scanf("%d", &limit_table); 는 오류가 발생해서 중간 과정 도입.
limit_table[age] = (unsigned char)temp;
*p[age] = (unsigned char *)malloc(limit_table[agㅂ2e]);
printf("\n%d0대 연령의 윗몸 일으키기 횟수\n", age + 2);
for (member = 0; member < limit_table[age]; member++)
{
printf("%dth:", member + 1);
scanf("%d", &temp);
*(p[age] + member) = (unsigned char)temp;
}
}
printf("\n\n연령별 평균 윗몸 일으키기 횟수\n");
for (age = 0; age < 3; age++)
{
sum = 0;
printf("%d0대 : ", age + 2);
for (member = 0; member < limit_table[age]; member++)
{
sum = sum + *(p[age] + member);
}
printf("%5.2f\n", (double)sum / limit_table[age]);
free(p[age]);
}
}
그렇다면 연령대 자체가 다양해진다면 어떻게 해야할까?
연령대를 입력받기 위한 값과, 각 연령대별 인원수를 입력받기 위한 값이 따로 주어져야할 것이다.
그리고 static하지 않고 가변적이어야 하므로 동적 할당을 이용해야한다.
#include <stdio.h>
#include <malloc.h>
void main()
{
/* 연령별 인원수를 저장할 포인터 - 사용자에게 입력 받음 */
unsigned char *p_limit_table;
/* 연령별 윗몸 일으키기 횟수를 저장할 2차원 포인터 */
unsigned char **p;
int age, age_step, member, temp, sum;
printf("20대부터 시작해서 연령층이 몇개인가요 : ");
scanf_s("%d", &age_step);
p_limit_table = (unsigned char*)malloc(age_step);
/* p가 가리키는 1차원 포인터를 age_step만큼 만듦.*/
p = (unsigned char**)malloc(sizeof(unsigned char*) * age_step);
/* 연령별로 윗몸 일으키기 횟수를 입력 받는다 */
for (age = 0; age < age_step; age++) {
printf("\n%d0대 연령의 윗몸 일으키기 횟수\n", age + 2);
printf("이 연령대는 몇 명입니까? : ");
/* 해당 연령에 소속된 사람수를 입력 받는다.*/
scanf_s("%d", &temp);
/* 입력 받은 인원수 만큼 메모리를 할당 한다
p_limit_table + age 는 1바이트씩 메모리를 이동해서 값을 참조한다고 이해하면됨.
char형태로 값을 받기 때문에 1바이트당 각 연령별 인원수가 저장되는 것과 같음.*/
*(p_limit_table + age) = (unsigned char)temp;
/* 위에서 age_step만큼 1차원 포인터를 선언했음.
각 1차원 포인터가 가리키는 최종값에 p_limit_table이 age영역에 참조한 정수를 입력한다. */
*(p + age) = (unsigned char*)malloc(*(p_limit_table + age));
/* 해당 연령에 소속된 사람들을 순서대로 입력 받는다. */
for (member = 0; member < *(p_limit_table + age); member++) {
printf("%dth : ", member + 1);
scanf_s("%d", &temp);
/* 2차원 포인터의 최종값에 적용 */
*(*(p + age) + member) = (unsigned char)temp;
}
}
printf("\n\n연령별 평균 윗몸 일으키기 횟수\n");
for (age = 0; age < age_step; age++) {
sum = 0;
printf("%d0대 : ", age + 2);
for (member = 0; member < *(p_limit_table + age); member++) {
sum = sum + *(*(p + age) + member);
}
printf("%5.2f\n", (double)sum / *(p_limit_table + age));
/* 이 연령에 할당했던 동적 메모리를 해제한다. */
free(*(p + age));
}
/* 윗몸 일으키기 횟수를 저장하기 위해서 구성했던 메모리를 해제한다. */
free(p);
/* 연령별 인원수를 기억하기 위해서 사용했던 메모리를 해제한다. */
free(p_limit_table);
}
'프로그래밍 공부 > C 공부' 카테고리의 다른 글
[C] 크기가 가변적인 배열 (동적할당 활용) (0) | 2021.01.12 |
---|---|
[C] 공부 소스 (0) | 2021.01.12 |
[C] 동적메모리 사용하기 (0) | 2021.01.10 |
[C] 동적 메모리 할당 및 해제 (0) | 2021.01.08 |
[C] 프로세스와 메모리할당 (0) | 2021.01.08 |