본문 바로가기

프로그래머스 풀스택 데브코스/데브코스 TIL

웹 풀사이클 데브코스 TIL 46일차

함수 포인터

함수명 앞에 *를 붙여주면 함수 포인터가 선언된다.

Int (*func)(int a);

예제코드이다.

int Add(int a, int b) {
    return a+b;
}

int Sub(int a, int b) {
    return a-b;
}

int main()
{
    int a = 20;
    int b = 10;

    int (*fPtr)(int pa, int pb);
    fPtr = Add;
    int result = fPtr(a, b);

    printf("결과값 : %d\n", result);
    return 0;
}

코드를 전혀 바꾸지 않고 포인터만 바꿔줌으로써 결과가 달라진다.
함수 포인터는 이런식으로도 사용할 수 있다.

int main()
{
    int a = 20;
    int b = 10;
    int select;

    int (*fPtr)(int pa, int pb);

    while(1) {
        scanf("%d", &select);
        switch(select) {
            case 1:
                fPtr = Add;
                break;
            case 2:
                fPtr = Sub;
                break;
            case 3:
                return 0;
            default:
                break;
        }
        int result = fPtr(a, b);
        printf("결과값 : %d\n", result);
    }
    return 0;
}

fPtr 하나로 여러 함수를 사용할 수 있는 것이다.

함수 포인터의 사용 이유

함수의 동적 바인딩을 위해 꼭 필요하다. 컴파일 시점에 결정되는 정적 바인딩이 아닌 런타임 시점에 결정되는 동적 바인딩 기능을 위해 필요하다. 프로그램의 유연한 확장성을 제공하는 것이다.
자바스크립트의 var도 동적바인딩이라 볼 수 있다. vscode의 extension은 플러그인 방식으로 동작하는데 이 또한 하나의 예시이다.

구조체

하나 이상의 서로 다른 종류의 변수들을 묶어서 새로운 데이터 타입을 정의한다. 연관관된 변수들을 하나로 묶어서 관리에 유용하다. 예를들어 학생 정보 시스템이 있고 변수로 이름, 나이, 성별이 있으면 각각의 변수로 별도로 관리하면 연관성을 알 수 없다. 하지만 학생이라는 구조체로 이를 묶어주면 편리하게 관리할 수 있다.
구조체 예시이다.

struct Student
{
    char name[10];
    int age;
    int height;
}

구조체 변수를 통해 구조체 맴버의 값을 참조할 수 있다.

st1.name, st1.age, st1.height

멤버에 접근 시 .(점)을 사용하는데 이를 직접 접근이라고 한다.

구조체를 다루는 예시 코드이다.

#include <string.h>

struct student {
    char name[10];
    int age;
    int height;
}st1;

int main()
{
    strcpy(st1.name, "홍길동");
    st1.age = 20;
    st1.height = 178;

    printf("이름: %s, 나이: %d, 키: %d\n", st1.name, st1.age, st1.height);

    return 0;
}

공용체

공용체 역시 사용자 정의 자료형이지만, 구조체와의 차이점은 메모리 공간을 공요한다.
이 개념은 타입스크립트에서도 사용된다.

union temp
{
    char a;
    int b;
    int c;
};

열거형

enum, 데이터들을 열거한 집합, 정수형 상수로 취급한다.

enum Week
{
    sun = 0;
    mon,
    tue,
    wed,
    thu,
    fri,
    sat
};

첫번째 멤버를 0으로 설정하면 다음 멤버는 1씩 증가한다.
enum의 사용 예시이다.

enum Week{
    sun = 1,
    mon,
    tue,
    wed,
    thu,
    fri,
    sat
};

int main()
{
    int day;
    printf("요일을 선택하세요 : ");
    scanf("%d", &day);

    switch(day) {
        case sun :
            printf("일요일\n");
            break;
        case mon :
            printf("월요일\n");
            break;
        case tue :
            printf("화요일\n");
            break;
        case wed :
            printf("수요일\n");
            break;
        case thu :
            printf("목요일\n");
            break;
        case fri :
            printf("금요일\n");
            break;
        case sat :
            printf("토요일\n");
            break;
        default:
            printf("잘못된 입력\n");         
    }
    return 0;
}

메모리 동적할당

힙 메모리는 큐 메모리라고도 함
동적할당을 하면 메모리의 힙영역에 저장된다. 힙은 컴파일 시가 아닌 런타임에서 사용자로부터 할당 메모리를 입력 받음.
동적으로 메모리를 할당하는 이유는 무엇인가?
만약 10개 사이즈의 배열을 만든다고 치자, 런타임에서 이 배열의 크기가 10명이 충분할 수 있지만 만약 더 필요하다면? 동적할당이 없다면 프로그램을 종료하고 다시 코드를 수정해야한다. 하지만 동적 할당을 사용하면 런타임에서 이 배열의 크기를 조정할 수 있다.

int main()
{
    int num;
    int *student;

    printf("학생 수를 입력하세요 : ");
    scanf("%d", &num);

    student = (int*)malloc(sizeof(int) * num);

    if(student == NULL) {
        printf("메모리가 할당되지 않았습니다.\n");
        return 0;
    }
    printf("할당된 메모리 크기는 %d입니다.\n", sizeof(int)*num);
    free(student);
    return 0;
}

c언어에서는 가비지 컬렉터가 없기 때문에 메모리 해제를 해주어야한다.
또 힙 기반 메모리는 단독으로 사용할 수없고 스택메모리에 그 주소를 포인터변수에 저장해서 사용해야한다.

객체지향

객체: 사물을 나타내는 추상적인 개념
지향: ~를 향한다.

구조적 프로그래밍: 순차적, 하향적, 폭포수 방식이락 한다. 기본 단위는 함수이다.
객체지향 프로그래밍: 기능 단위가 객체. 예시로 이벤트 기반의 윈도우 프로그램이 있다.

추상화

공통적인 특징들을 뽑아서 하나의 객체를 만든다.
추상: 대상에서 특징만을 뽑아낸 것
플라톤의 이데아와 일맥상통하는 개념이다. 본질과 현상을 분리해서 본다. 개의 본질은 관념속에 있고, 우리가 보는건 삽살개, 진돗개, 치와와 라는 말이다.

캡슐화

은닉하다, 숨긴다는 의미.
외부에서 그 내부를 볼 수 없게 한다.
외부로부터 데이터를 조작하려면 인터페이스를 통해서 한다.

후기

함수 포인터, 구조체, 동적할당에 대해서 학습하였고, 객체지향에 대해서도 알아보았다.
객체의 데이터 = 프로퍼티, 필드, 속성, 멤버변수
멤버 함수 = 메소드

키워드: 프로그래머스 데브코스, 국비지원교육, 코딩부트캠프