211103, C언어 입문 day 13-2

Min Hyeok·2021년 11월 3일
0

C언어 개념 익히기

목록 보기
17/19

어제는 몸 컨디션도 그렇고, 하루죙일 피곤했다. 그래서 오늘 왔다.
오늘은 이거 말고도 복습할 내용이 많아서, 빨리빨리 복습해보도록하자.

17-3

앞서 포인터를 공부 하면서, 함수의 매개변수로 포인터를 사용하는 경우도 있었다. 물론, 이차원포인터들도 함수의 매개변수로 사용할 수 있겠지.

대신, 차원 개념을 익히며 한 층 더 깊게 들어온 만큼 차원 개념을 잘못 적용하면 원하는 값을 받지 못할 수도 있다.

예시 코드를 하나 보자.

void MallocData(int *q) { //MallocData가 호출 되면 8바이트 동적 할당 해줌

    q = (int *) malloc(8);

}

int main() {

    int *p;
    MallocData(p);
    *p = 6;
    free(p);

}

이게 될까?

Nope. 어림도 없다.

main 함수에서 p를 인지하고 MallocData까지는 잘 넘어갈 수 있다. 그리고 q = p인것도 받아들이고. 그런데 그 다음에 보면 q에는 8바이트 메모리가 할당은 된다. 그런데 p에는 영향을 미치지 않는다. p는 초기화 되지 않은 쓰레기 값을 가지고 있는데, 거기에 5를 저장하려고 하면 의도하지 않은 주소에 값을 넣기 때문에, 오류가 발생한다.

애초에 우리는 p에 어떤 메모리의 주소 값을 넣어준 적 조차 없으니까, 되지도 않는 주소로 이동해서 값을 대입하는거다.

이걸 해결해주려면 어떻게 해야하는가.

우린 여기서 앞서 배운 다차원 포인터에 대한 개념을 써줄거다.

앞서 13-1일차에 동그라미 그림 세개 그려놓고 2차원 1차원 0차원이라고 설명한 적이 있다. 그걸 여기 응용해주면,

void MallocData(int **q) {
    *q = (int *)malloc(8);
}

int main() {
    int *p;
    MallocData(&p);
    *p = 6;
    free(p);
}

이렇게 해준다면, 어떻게 될까?

우선 포인터 변수 p를 set 해주고, MallocData에 "p의 주소값"을 전달해준다. 그러면 2차원 포인터 q에 1차원 포인터 p의 주소값이 저장이 되겠지.

그 다음으로 MallocData에서 8바이트만큼 동적 메모리 할당을 해주는데, q가 가리키는 포인터 변수 p에다가 해준다. 그 다음, main 함수로 넘어가서 p가 가리키는 대상 (MallocData에서 8바이트만큼 동적 할당을 해준 그 곳)에 값 6을 대입. 그다음 free 해주고 프로그램 끝.

깔끔하다.

17-4.

2차원 포인터와 2차원 배열.. 이라는 part다. 뭘 말하고 싶은지 들여다보자.

정적 할당은 여러모로 단점이 많았었다. 배열의 메모리 크기를 상수로 밖에 못 넣어서 조금 유동적으로 바꿀 수 없었다.

그리고 포인터 배열도 마찬가지다. 이를 동적할당개념과 섞어서 써보도록 하자.

1차원 포인터 여러개를 동적 할당 하는데, 이게 "몇 개(n개)"인지를 사용자가 임의로 설정하고 싶다고 치자.

int n;
short **pp;
scanf("%d", &n); // n 을 입력받음
pp = (short **) malloc(sizeof(short *) * n); // n개만큼 메모리 동적 할당

이렇게 쓰면, 포인터 (pp+0)부터 포인터 (pp+(n-1))까지 n개를 배열처럼 쓸 수 있다. 포인터 배열의 개수가 변하더라도 상수가 아니라 프로그램 실행 중 가변적으로 변할 수 있으므로 다시 컴파일 할 필요가 없단 말씀.

앞에서는 2차원 포인터를 사용하여 1차원 배열(1차원 포인터)처럼 사용하는 방법을 설명했는데, 이번에는 2차원 배열과 같은 용도로 사용할 수 있는 메모리를 동적 할당 하는 방법을 살펴보겠다.

이건 교재에 있는 예시와 함께 코드를 적으면서 설명하겠다.

어떤 회사에서 직원들의 체력을 테스트한 결과를 저장하는 프로그램.
20대가 4명, 30대가 2명, 40대가 3명
1분간 윗몸 일으키기를 하고, 이 횟수를 연령별로 저장

  • 443 page.

완성본 코드를 적으면서, 중간 중간 주석을 넣겠다.

#include <stdio.h>
#include <malloc.h>

int main() {

    unsigned char *p_limit_table; //연령별 인원수 저장
    
    unsigned char **p //연령별 윗몸 일으키기 횟수 저장
    
    int age, age_step, member, temp, sum;
    
    printf("20대부터 연령층 개수 : ");
    
    scanf("%d", &age_step);
    // 만약 3개면 20, 30, 40대 총 세개의 연령대
    
    p_limit_table = (unsigned char**) malloc(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("%d, &temp); //각 연령대 별로 몇 명이 있는지.
        *(p_limit_table + age) = (unsigned char) temp;
        // p_limit_table[age] = temp와 같은 표현
        
        *(p + age) = (unsigned char *)malloc(*(p_limit_table + age));
        //입력받은 인원수 만큼 메모리를 할당한다.
        for(member = 0 ; member < *(p_limit_table + age) ; member++) {
            printf("%dth : ", member + 1); //각 사람마다 윗몸 횟수 입력받음
            scanf("%d", &temp);
            *(*(p + age) + member) = (unsigned char) temp;
            // p[age][member]와 같은 표현.
        }   
    }
    
    .. 이후 연령별 윗몸일으키기 횟수 입력받고 free

}

위의 코드를 읽으면서 해석하자. 설명이 필요한 부분은 상세하게 주석을 하나하나 달아놨다. 조금 어려울 수도 있지만, 천천히 읽으면서 익히면 된다.

여기까지.

0개의 댓글