Eat Study Love

먹고 공부하고 사랑하라

SW 만학도/C

Review 5 - Dynamic(Structure) in C

eatplaylove 2024. 7. 8. 21:55

https://eglife.tistory.com/76

 

Review 4 - File I / O in C

https://eglife.tistory.com/71 Review 3 - Pointer & Array in Chttps://eglife.tistory.com/70 Review 2 - Control Structures / Functions in Chttps://eglife.tistory.com/69 Review 1 - C programming basics이번엔 C 언어에 대한 복습이다. Python, C,

eglife.tistory.com

은근 복잡한 C에서의 I / O 기회될 때마다 복습 요망

1. Structure

 

C에선 Class가 없고 Structure만 있다.(C++에 Class가 있음)

단, Structure에는 Method가 없다.

 

Python의 List는 여러 type의 variable을 포함하는 object를 만들게 해준다. C++에선 Class를 쓰면 되고,,

C에선 Structure를 선언한다.

Method는 없당

그저 Variable들의 Group이다.

 

struct를 선언하면, 그 자체가 하나의 Type이 된다. 단, Data type을 "struct studentType" 까지가 Data type이다. 한 번에 다~ 써야 한다.

Structure Memory type

Structure의 Memory 형태를 살펴보면, 일전에 배웠던 Array처럼 Memory들이 뭉쳐서 표현되어 있다.

 

근데, structure studentType 이렇게 다 쓰기가 구찮다. 그래서 "type def"를 써준다.

 

일종의 customizing이 가능하다. 기존 것을 그냥 쓰는 것도 가능은 하다. 그냥 type def로 별명이 하나 더 늘어난 것

 

 

#include <stdio.h>
#define STUDENT_NUMS 5
struct studentType{

    char name[10];
    int mid;
    int final;
    int total;
};
typedef struct studentType Student;

void calculation(Student *s);

int main(void){

    Student s[STUDENT_NUMS];
    // scanf input
    for(int i = 0 ; i < STUDENT_NUMS; i++){
        printf("Input for student # %d \n",i);
        printf("name :\n");
        scanf("%s",s[i].name); // char은 array형태라 이미 주소임. & 쓰지 않는다.
        printf("mid: \n");
        scanf("%d",&s[i].mid);
        printf("final: \n");
        scanf("%d",&s[i].final);
    }

    // calculate total
    for(int i = 0 ; i < STUDENT_NUMS ; i++){
        // s[i].total = s[i].mid + s[i].final; //이렇게 해도 된다.
        calculation(&s[i]);
    }

    // print out
    for(int i = 0 ; i < STUDENT_NUMS ; i++){
        printf("Total score of %d(%s) student is %d\n",i,s[i].name,s[i].total);
    }
    return 0;
}

void calculation(Student *s){
    s->total = s->mid + s->final;
    return;    
}
// test
Total score of 0(qwer) student is 2
Total score of 1(asdf) student is 4
Total score of 2(zxcv) student is 6
Total score of 3(tyui) student is 8
Total score of 4(vbnm) student is 10

 

struct + ~~~ 까지 이름을 적어야 그거까지 합쳐서 data type이다. 그리고 struct, 함수 declaration할 때 세미콜론 잊지 말자.

typedef에도 세미콜론 잊지 말자구!

 

 

2. Dynamic memory Allocation

 

Array와 Linked List의 장단점은 항상 잘 숙지하고 있어야 한다.

Run - time Stack엔 깔끔한 규칙에 의해 늘었다 줄었다 하며,

 

초반에 큼직한 것들은 죄다 Stack Memory에 쌓는다. Array 같은 것들도 고정 값이니 Run time Stack에 할당된다.

 

반면, Linked List 같이 늘었다 줄었다가 반복적인 친구는 Array 같은 다소 딱딱한 구조에 Memory를 할당하면 비효율적이라 Heap이라는 영역에 할당하며 이를 Dynamic Memory Allocation, 메모리 동적할당이라고 한다.

 

 

Stack vs Heap 비교

 

Stack 영역은 자동적으로 메모리가 할당/비할당 된다 by compiler

 

Heap 영역은 User가 수동적으로 메모리를 할당하고 없애고 해야한다. Programmer가 Heap에 할당한 Memory를 계속 놔두면 계~속 존재한다.

 

Stack은 그래서 Memory 중간 중간에 구멍이 뚫리지 않는데, Heap은 User가 만들었다가 지웠다가 하므로 중간에 빵꾸가 날 수도 있다; -> Inefficient Memory 활용

 

Stack은 위로 쌓임(Memory주소 작아지는 방향) Heap은 아래로 쌓임(Memory주소 커지는 방향)

 

User가 Dynamic Memory Allocation을 하는 Command = 멜록 [MALLOC]

 

stdlib.h 라는 헤더가 필요하다 for malloc

※ lack of memory로 malloc 이 실패하면 NULL ptr을 return한다. 이를 반드시 초반에 체크하자.

※ heap에 할당된 녀석은 deallocate command를 날리기 전까지 무병장수한다. 반드시 deallocate를 하자

 

 

좌측처럼 쓰면 type이 void* 이다. 그래서 우측처럼 type cast를 해줘야 정확한 return값을 받는 것이다.

 

deallocate 할 땐, free(intPtr)  . . . free(sPtr) 이렇게 free를 해줘야 한다.

 

#include "stdio.h"
#include "stdlib.h"

int main(void){

    int a = 123456;
    int b = 999777;

    int *intptr  = &a;
    printf("a:%d, *ptr:%d\n",a,*intptr);
    intptr = (int*)malloc(sizeof(a));
    *intptr = b;
    printf("a:%d, *ptr:%d\n",b,*intptr);
    *intptr = a;
    printf("a:%d, *ptr:%d\n",a,*intptr);
    free(intptr);

    return 0;
}

 

malloc 가지고 놀기..

 

이렇게 malloc 을 이용하면 같은 이름의 intptr인데도 a에 할당했다~ b에 할당했다~ 하면서 free 전까지 마음대로 가지고 놀 수가 있다.

 

근데 malloc을 쓰지 않으면 그게 안 된당

 

    int a = 123456;
    int b = 999777;

    int *intptr  = &a;
    printf("a:%d, *ptr:%d\n",a,*intptr);
    int *intptr  = &b;
    printf("a:%d, *ptr:%d\n",b,*intptr);
//Error
    malloc.c: In function 'main':
malloc.c:11:10: error: redefinition of 'intptr'
     int *intptr  = &b;
          ^~~~~~
malloc.c:9:10: note: previous definition of 'intptr' was here
     int *intptr  = &a;
          ^~~~~~

 

malloc을 써서 size를 극단적으로 작게했는데도 일단 출력은 아래와 같이 정상적으로 된다.

 

불안정하지만 Heap 특성상 우연히 memory 공간에 여유가 있어서 코드가 잘 진행된 case.

 

그치만 이왕이면 size를 넉넉히 heap에 할당하는 게 안전하고 좋다.

 

    int a = 123456;
    int b = 999777;
    int c = 987654321;
    int *intptr;
    intptr = (int*)malloc(1);
    *intptr = a;
    printf("a print:%d\n",*intptr);
    *intptr = b;
    printf("b print:%d\n",*intptr);
    // 일부로 size over 되게 request
    *intptr = c;
    printf("c print:%d\n",*intptr);

    free(intptr);

    return 0;
}
// test
a print:123456
b print:999777
c print:987654321

 

malloc이 정상적으로 작동하지 않는 걸 체크하는 건 아래와 같이 진행!

 

    if(intptr == NULL){
        //error
        fprintf(stderr,"ERR\n");
        return -1;
    }

 

이제 이 Dynamic 할당 ( malloc + free )으로 C에서도 Linked List를 만들 수 있다..

 

거기까지만 잘 공부해보자

 

- E. O. D -

 

'SW 만학도 > C' 카테고리의 다른 글

C programming file I/O 연습  (0) 2024.08.21
Review 6 - Linked list in C  (0) 2024.07.10
Review 4 - File I / O in C  (0) 2024.07.07
Review 3 - Pointer & Array in C  (0) 2024.07.04
Review 2 - Control Structures / Functions in C  (0) 2024.07.03