모바일 오유 바로가기
http://m.todayhumor.co.kr
분류 게시판
베스트
  • 베스트오브베스트
  • 베스트
  • 오늘의베스트
  • 유머
  • 유머자료
  • 유머글
  • 이야기
  • 자유
  • 고민
  • 연애
  • 결혼생활
  • 좋은글
  • 자랑
  • 공포
  • 멘붕
  • 사이다
  • 군대
  • 밀리터리
  • 미스터리
  • 술한잔
  • 오늘있잖아요
  • 투표인증
  • 새해
  • 이슈
  • 시사
  • 시사아카이브
  • 사회면
  • 사건사고
  • 생활
  • 패션
  • 패션착샷
  • 아동패션착샷
  • 뷰티
  • 인테리어
  • DIY
  • 요리
  • 커피&차
  • 육아
  • 법률
  • 동물
  • 지식
  • 취업정보
  • 식물
  • 다이어트
  • 의료
  • 영어
  • 맛집
  • 추천사이트
  • 해외직구
  • 취미
  • 사진
  • 사진강좌
  • 카메라
  • 만화
  • 애니메이션
  • 포니
  • 자전거
  • 자동차
  • 여행
  • 바이크
  • 민물낚시
  • 바다낚시
  • 장난감
  • 그림판
  • 학술
  • 경제
  • 역사
  • 예술
  • 과학
  • 철학
  • 심리학
  • 방송연예
  • 연예
  • 음악
  • 음악찾기
  • 악기
  • 음향기기
  • 영화
  • 다큐멘터리
  • 국내드라마
  • 해외드라마
  • 예능
  • 팟케스트
  • 방송프로그램
  • 무한도전
  • 더지니어스
  • 개그콘서트
  • 런닝맨
  • 나가수
  • 디지털
  • 컴퓨터
  • 프로그래머
  • IT
  • 안티바이러스
  • 애플
  • 안드로이드
  • 스마트폰
  • 윈도우폰
  • 심비안
  • 스포츠
  • 스포츠
  • 축구
  • 야구
  • 농구
  • 바둑
  • 야구팀
  • 삼성
  • 두산
  • NC
  • 넥센
  • 한화
  • SK
  • 기아
  • 롯데
  • LG
  • KT
  • 메이저리그
  • 일본프로야구리그
  • 게임1
  • 플래시게임
  • 게임토론방
  • 엑스박스
  • 플레이스테이션
  • 닌텐도
  • 모바일게임
  • 게임2
  • 던전앤파이터
  • 마비노기
  • 마비노기영웅전
  • 하스스톤
  • 히어로즈오브더스톰
  • gta5
  • 디아블로
  • 디아블로2
  • 피파온라인2
  • 피파온라인3
  • 워크래프트
  • 월드오브워크래프트
  • 밀리언아서
  • 월드오브탱크
  • 블레이드앤소울
  • 검은사막
  • 스타크래프트
  • 스타크래프트2
  • 베틀필드3
  • 마인크래프트
  • 데이즈
  • 문명
  • 서든어택
  • 테라
  • 아이온
  • 심시티5
  • 프리스타일풋볼
  • 스페셜포스
  • 사이퍼즈
  • 도타2
  • 메이플스토리1
  • 메이플스토리2
  • 오버워치
  • 오버워치그룹모집
  • 포켓몬고
  • 파이널판타지14
  • 배틀그라운드
  • 기타
  • 종교
  • 단어장
  • 자료창고
  • 운영
  • 공지사항
  • 오유운영
  • 게시판신청
  • 보류
  • 임시게시판
  • 메르스
  • 세월호
  • 원전사고
  • 2016리오올림픽
  • 2018평창올림픽
  • 코로나19
  • 2020도쿄올림픽
  • 게시판찾기
  • 오유인페이지
    개인차단 상태
    Haskell님의
    개인페이지입니다
    가입 : 11-06-13
    방문 : 1069회
    닉네임변경 이력
    회원차단
    회원차단해제
    게시물ID : programmer_13292
    작성자 : Haskell
    추천 : 11
    조회수 : 1129
    IP : 119.67.***.161
    댓글 : 23개
    등록시간 : 2015/09/14 23:42:54
    http://todayhumor.com/?programmer_13292 모바일
    [C언어] Memory Allocation (malloc)에 관해서
    옵션
    • 창작글
    • 외부펌금지
    틀린 내용이 있을 수도 있으니, 자세한 내용은 더 검색해보시길 바랍니다...ㅎㅎ (그리고 덧글로 틀린부분 태클 걸어주시면 겸허히 고치겠습니다.)
    오유 가입하고 처음 적는 글이 팁이네요... @_@ (이런 진지한 글 오유랑 안어울리는거 같아요... ;ㅁ;)

    들어가며...


    C언어를 공부하는 과정에서 배열을 배우시고 나면 이런 질문을 던지시게 됩니다. 
    대표적으로 "배열의 크기를 입력받아 할당하는 방법은 없을까?" 이런 질문 말이죠...ㅎㅎ
    일단 질문에 대한 답으로 다음과 같은 코드를 작성할 수 있습니다. (꽤 의미깊은 코드임)

    #include <stdio.h>

    #include <string.h>


    int main(int argc, const char * argv[]) {

        

        int i = 0;

        unsigned long arr_size  = 0;

        

        printf("생성할 배열의 크기를 입력해주세요: ");

        scanf("%lu", &arr_size);

        

        int arr[arr_size]; memset(arr, 0, arr_size);

        

        printf("\n");

        

        for(int i = 0; i < arr_size; i++) {

            printf("배열에 추가할 %d번째 숫자 입력: ", i);

            scanf("%d", &arr[i]);

        }

        

        

        for(i = 0; i < arr_size; i++) {

            printf("배열에 추가할 %d번째 숫자: %d\n", i, arr[i]);

        }

        

        return 0;

    }

    일단 어떤 목적으로 작성한 코드인지 간단히 설명해드리자면 아래와 같습니다.
    1. 배열의 크기를 사용자로 부터 입력받아 arr_size에 저장
    2. arr 배열을 1번에서 입력받은 arr_size로 초기화
    3. memset을 사용하여 배열의 모든 값을 0으로 초기화
    4. 배열에 사용자가 입력한 정수 데이터를 저장 (첫번째 for loop)
    5. 배열에 저장된 데이터를 화면에 출력 (두번째 for loop)
    저 코드가 약간 논란이 될 수도 있는데요, 그 이유는 컴파일러에 따라 컴파일이 될 수도 있고, 안될 수도 있기 때문입니다.
    조금더 상세히 말씀드리자면, C99 Standard를 지원하는 컴파일러는 위의 코드가 컴파일이 잘 됩니다만, C99 Standard를 아직 지원하지 않는 컴파일러는 2번과 4번에서 오류가 날거에요.

    2번은 Variable Length Arrays (줄여서 VLA) 라고 가변길이배열인데, 원래는 입력 받은 크기를 malloc 이라는 Memory Allocation 함수를 사용하여 크기만큼 메모리를 가변적으로 할당하여야 했습니다만 이젠 컴파일러가 해줍니다.
    4번은 타 언어처럼 For 루프 선언 부분에서도 저렇게 변수를 선언할 수 있게 되었습니다. (원래는 위에 i 선언해두고 시작했어야했죠...ㅎㅎ)

    뭐 C99 이후부터 C++과 비슷하게 저런 것들이 가능하니 저거 컴파일 되신다면 사실 이문서 읽지 마시고 저거 쓰시면 됩니다. (끝)
    근데 교수님들이 저런거 안좋아하시고 또 잘 모르십니다... (보통 80년대 중반에 대학다니셨던 분들이셔서...)

    일단 위의 코드는 그냥 요즘 C는 이런게 된다~ 이런걸 보여드리려고 작성해둔 것이고요ㅎㅎ
    여기에서는 일단 C99의 신기술(?)을 사용하지 않고 구현하는 방법에 대해 알아보도록 하겠습니다.

    일단 배열이 뭐시당가?


    배열은 간단히 말해서 연속된 자료형이라 할 수 있고, 내부의 처리 루틴을 기반으로 말하자면 메모리의 연속이라고 말할 수 있습니다.
    아니 그게 무슨소리요? 하실건데요, 아래 소스코드를 한번 컴파일하여 실행해보시죠..ㅎㅎ

    #include <stdio.h>


    int main(int argc, const char * argv[]) {

        

        int b[5] = {01234};

        int i = 0;

        

        printf("b = %p = %d\n", b, *b);

        

        for(i = 0; i < 5; i++) {

            printf("b[%d] = %p = %d\n", i, &b[i], b[i]);

        }

        

        printf("\n");

        

        for(i = 0; i < 5; i++) {

            printf("b[%d] = %p = %d\n", i, b+i, *b+i);

        }

        

        return 0;

    }

    첫번째 루프는 기존 알고있었던 배열의 접근 방식으로 접근을 한 것이고, 두번째 루프는 배열을 포인터 계산을 통해 접근하는 방법입니다.
    일단 b[0]과 b는 값부터 주소까지 똑같이 나올 것입니다. 그리고 루프 2개의 출력 값 또한 동일할거에요.

    여기서 유의깊게 봐야하는 코드는 바로 두번째 for 루프입니다.
    요상하게도 포인터로도 배열의 값에 접근이 가능합니다. 그 이유는 바로 정수형 배열로 선언되어 있는 b가 사실은 포인터 변수이기 때문입니다.
    즉, b는 더도말고 덜도말고 그저 배열의 시작주소를 가리키고 있는 포인터 변수입니다. (아마 책에서 읽으셨을거에요. b 자체는 배열의 시작주소를 가리키고 있다고 말이죠)
    따라서 내부에서는 "int b[5]"라고 선언하는 순간 b에는 int의 크기에다가 배열의 크기(5)를 곱한 만큼의 공간이 비어있는 어느 메모리 공간의 시작주소가 저장되는 것입니다.
    그러므로 위의 코드에서는 "int b[5]"같은 경우에는 연속해서 20바이트의 공간이 비어있는 메모리 공간의 시작주소가 b에 저장된다고 볼 수 있겠습니다.
    정리해보자면 배열은 내부적으로는 두번째 루프에서와 같이 포인터로 접근 하는 것인데, 사람이 알아보기 어려우니 보기좋게 하기 위해서 b[0]과 같은 방법으로 접근할 수 있게 해둔 것이죠. (이를 Syntactic Sugaring, '달콤한 문법' 이라고 합니다) 

    뭔가 약간의 감이 오지 않습니까?ㅎㅎ

    그렇다면 동적할당을 어떻게 구현할 수 있을까?


    이제 동적할당을 어떻게 구현 할 수 있을지 고민해봅시다. (저는 컴퓨터에서 문제 해결에서 방법만이 아닌 원리 또한 알아야된다 생각해서요....ㅋㅋㅋ)
    아래의 간단한 코드를 32비트 머신에서 최적화 없이 컴파일하여 실행한다고 가정해보도록 하겠습니다.

    #include <stdio.h>


    int main(int argc, const char * argv[]) {

        

        int a;

        

        return 0;

    }

    위의 코드를 실행하면 4바이트의 정수형 변수 a가 메모리의 어느 부분에 생성이 될겁니다. 그림으로 그리자면 메모리에 다음과 같이 위치하고 있을거에요. (가정)

    001 005 009   013 017  021  025  029 
     a




     

    이제 여기다가 정수가 5개정도 들어가는 정수형 배열을 추가적으로 선언하고 싶어요. 일단 정적배열로 선언 해본다면,

    #include <stdio.h>


    int main(int argc, const char * argv[]) {

        

        int a;

        int b[5];

        

        return 0;

    }

    그렇다면 코드가 위와같이 될 것이고, 메모리에 다음과 같이 위치하게 될 것입니다. (가정)

    001 005 009   013 017  021  025  029 
     a  b [0] b[1] b[2] b[3]  b[4]  b[5]   

    이말은 즉, 정적 배열 선언시 005에서 부터 4바이트씩 025까지 크기가 20바이트 만큼의 공간을 가진 배열 b가 선언되게 됩니다. 그리고 b에는 그 20바이트의 시작주소가 들어가게 되는 것이죠.
    그렇다면 동적 선언도 저렇게 해버리면 되지 않을까요? 정리해서, 자료형의 크기에서 데이터 개수 만큼의 메모리 공간을 할당받고, 그 시작주소를 변수에 저장하면 되지 않을까요?
    네 그렇게 하면 됩니다. (원리가 그거에요) 의외로 간단하쥬?

    메모리 동적 할당 함수 : malloc


    서론이 조금 길었던 것 같은데요, 이걸 어떻게 할 수 있을까요? "malloc" 이라는 함수를 알아보도록 하죠.

    malloc는 이름을 보면 알 수 있듯이 Memory Allocation 의 준말로 메모리 할당에 관여하는 함수입니다. stdlib.h 라는 헤더 파일에 선언되어 있으므로 사용시에는 stdlib.h를 include 해주셔야 합니다.
    stdlib.h 내 선언되어있는 malloc의 함수명세는 다음과 같습니다.

    void *malloc(size_t);

    void이지만(자료형이 정해져있지 않기 때문에) 실제로는 size_t 만큼의 공간을 할당하여 그 시작주소를 반환하는 함수입니다. size_t는 간단하게 바이트 크기라고 생각하시면 됩니다.

    예를들어 정수형 자료 6개가 들어갈 수 있는 공간을 할당해본다고 해봅시다. 코드를 한줄 한줄 작성해나가 BOA요~
    1. 먼저 include 부분과 main 함수를 작성합시다.

      #include <stdio.h>

      #include <stdlib.h>


      int main(int argc, const char * argv[]) {

          

          return 0;


      }

    2. 그리고 정수형 자료 6개가 들어있는 공간의 시작주소를 가리켜야 할 포인터 변수 "p"를 하나 선언해봅시다. (p는 포인터 변수이니 스타가 붙어야겠죠?)

      int main(int argc, const char * argv[]) {

          

          int* p;

          

          return 0;

          

      }

    3. 그리고 정수형 자료의 크기를 가진 정수형 변수 "size_int"를 하나 선언해봅시다. ( sizeof 함수 다들 아시죠?)

      int main(int argc, const char * argv[]) {

          

          int *p;

          

          // sizeof(변수 또는 자료형) 인자로 받은 변수 또는 자료형의 크기를 반환하는 함수입니다.

          // 여기서는 정수의 크기 (int)가 필요하므로, sizeof(int)가 되겠죠?

          int size_int = sizeof(int);

          

          return 0;

          

      }

    4. 마지막으로 정수형 자료 6개의 크기를 가진 정수형 변수 "size_int6"를 하나 선언해봅시다. (정수형 자료 6개의 크기는 size_int의 6배와 같겠죠?)

      int main(int argc, const char * argv[]) {

          

          int *p;

          

          int size_int  = sizeof(int);

          int size_int6 = size_int * 6;

          

          return 0;

          

      }

    5. 이제 동적할당을 해보도록 하죠. malloc의 인자는 할당할 메모리의 크기라고 했습니다. 따라서 정수형 자료 6개의 크기를 가진 size_int6을 인자로 넣으면 되겠죠?

      int main(int argc, const char * argv[]) {

          

          int *p;

          

          int size_int  = sizeof(int);

          int size_int6 = size_int * 6;

          

          p = malloc(size_int6);

          

          return 0;

          

      }

    6. 하지만 위의 코드는 뭔가 이상합니다. 찾으셨나요? 네 맞습니다! 자료형이 일치하지 않아요. malloc은 void 이지만, p는 int* 자료형이죠. 형변환을 해줍니다.

      int main(int argc, const char * argv[]) {

          

          int *p;

          

          int size_int  = sizeof(int);

          int size_int6 = size_int * 6;

          

          p = (int *)malloc(size_int6);

          

          return 0;

          

      }

    7. 코드가 약간 지저분 하니 깔끔하게 바꿔볼까요?

      int main(int argc, const char * argv[]) {

          

          int *p;

          p = (int *)malloc(sizeof(int) * 6);

          

          return 0;

          

      }

    즉 위와같이 malloc을 사용할 수 있습니다. 이해가 좀 되시나요?ㅎㅎ 이제 빠르게 사용할 수 있도록 일반화 시켜보도록 합시다.

    자료형 *p;

    p = (자료형 *)malloc(sizeof(자료형) * 할당크기);


    그렇다면 자료 접근은 어떻게 할 수 있을까요? 아실 것 같지 않나요? 네~ 배열의 자료를 접근하듯이 자료를 접근하시면 됩니다. (아래는 예제 코드입니다)

    #include <stdio.h>

    #include <stdlib.h>


    int main(int argc, const char * argv[]) {

        

        int* p;

        int  i;

        

        p = (int *)malloc(sizeof(int) * 4);

        

        for(i = 0; i < 4; i++) {

            p[i] = i;

        }

        

        for(i = 0; i < 4; i++) {

            printf("p[%d] = %d\n", i, p[i]);

        }

        

        return 0;

        

    }


    의외로 간단하죠?ㅎㅎ 하지만 메모리 동적할당의 단점이 있다면, 코드가 실행 된 이후에 할당된 부분이므로, 사용이 끝나면 직접 해제해주셔야 합니다.
    그렇다면 해제는 어떻게 하느냐? 이거도 진짜진짜 간단합니다. "free"라는 함수를 사용하시면 됩니다. 일단 free 함수의 명세를 살펴보도록 하죠.

    void free(void *);

    리턴 값은 없고요, 파라메터로는 메모리에서 해제할 변수를 넘기시면 됩니다. 즉, 위의 코드에서는 다음과 같이 사용할 수 있겠습니다.

    #include <stdio.h>

    #include <stdlib.h>


    int main(int argc, const char * argv[]) {

        

        int* p;

        int  i;

        

        p = (int *)malloc(sizeof(int) * 4);

        

        for(i = 0; i < 4; i++) {

            p[i] = i;

        }

        

        for(i = 0; i < 4; i++) {

            printf("p[%d] = %d\n", i, p[i]);

        }

        

        free(p); 

        

        return 0;

        

    }

    하지만 위는 그렇게 좋은 코드는 아닙니다. "free(p)"를 실행하였다고 하더라도, 메모리가 반환된 이후 그 부분이 사용되기 전까지는 그 값이 남아있기 때문이죠.
    따라서 자칫하면 약간의 혼란을 가져올 수 도 있는데요, 따라서 "free(p)" 이후, p가 가지고 있는 주소 자체도 NULL로 바꿔주시는게 좋습니다...ㅎㅎ (그러면 기타 문제를 미연에 방지할 수 있음)

    #include <stdio.h>

    #include <stdlib.h>


    int main(int argc, const char * argv[]) {

        

        int* p;

        int  i;

        

        p = (int *)malloc(sizeof(int) * 4);

        

        for(i = 0; i < 4; i++) {

            p[i] = i;

        }

        

        for(i = 0; i < 4; i++) {

            printf("p[%d] = %d\n", i, p[i]);

        }

        

        free(p); p = NULL;

        

        return 0;

        

    }


    결론


    게시판을 읽던 도중 질문을 받게되어 작성해본 글인데...., 간만에 글을 써보는 터라 어떨지 모르겠습니다. :b
    사실 지금은 C를 안한지 꽤 되어서 대부분 까먹었기도 하고 해서요....ㅋㅋㅋㅋㅋㅋ

    그리고 여기서는 malloc 하나만 알아보았지만, realloc 등 메모리에 대한 더 많은 함수들이 있으니  궁금하신 분들은 "C 동적 메모리 할당" 키워드로 구글링 해보시면 더 자세하고 쉽게 기술된 문서들이 많으니 참고하시면 될 것 같습니다.
    진짜 기초적인거만 쓴거라서.... =_=;;; 그래도 알찬거 같기도 하고요

    적고나니 부끄럽네요 @_@;;; 실력이 좋지도 못한데.... 이렇게 적어보니 공부 더 많이 해야되겠다고 느꼈습니다... ;ㅁ;
    열심히 해요 우리......


    출처 제가 공부한 것들의 기억....
    Haskell의 꼬릿말입니다
    꼬리가 길면 밟혀요..?

    이 게시물을 추천한 분들의 목록입니다.
    [1] 2015/09/15 01:37:44  121.151.***.138  GoToTheMoon  586722
    [2] 2015/09/15 07:16:50  124.199.***.40  불꽃남자대만  139732
    [3] 2015/09/15 09:10:26  211.232.***.252  Hello,World!  138634
    [4] 2015/09/15 09:37:04  124.137.***.43  kosi  439167
    [5] 2015/09/15 11:18:22  223.194.***.120  작은돼지  140557
    [6] 2015/09/15 11:34:23  61.107.***.130  슝슝3  284767
    [7] 2015/09/16 01:03:03  175.197.***.64  wonis  155362
    [8] 2015/09/16 10:03:39  123.141.***.115  휴뉴뉴?  374233
    [9] 2015/09/16 13:40:09  27.122.***.76  re0201  136641
    [10] 2015/09/17 14:53:48  223.62.***.77  세라프메이트  244943
    푸르딩딩:추천수 3이상 댓글은 배경색이 바뀝니다.
    (단,비공감수가 추천수의 1/3 초과시 해당없음)

    죄송합니다. 댓글 작성은 회원만 가능합니다.

    번호 제 목 이름 날짜 조회 추천
    10
    뉴질랜드 오클랜드 퀸 스트릿 스벅인데 앞의 분이 오유하시네여. [10] 창작글 Haskell 18/08/14 15:42 1040 24
    9
    Celine Dion - The Power of Love [3] Haskell 17/06/13 21:24 36 8
    8
    황규영 - 나는 문제없어 [1] Haskell 17/06/07 20:32 34 6
    7
    Apache - The incredible bongo band [2] Haskell 17/06/05 22:32 25 6
    6
    The Weather Girls - It's Raining Men [2] Haskell 17/05/28 21:24 32 5
    5
    엉엉 쾌변 후 변기에 아이폰 빠뜨렸어요....ㅜㅜ [2] Haskell 17/05/21 00:51 57 12
    4
    (스압) 인종차별이 없는 사회 만드는 것이 어려울까요. [1] 펌글 Haskell 17/04/01 23:51 61 3
    3
    방금 편의점에서 들은 노래인데요... 본인삭제금지 Haskell 17/01/09 16:41 31 0
    2
    클리앙이 현재 접속이 안되는데, 혹시 무슨 일인지 아시는 분? 본인삭제금지 Haskell 16/07/03 15:06 48 0
    [C언어] Memory Allocation (malloc)에 관해서 [10] 창작글외부펌금지 Haskell 15/09/14 23:42 35 11
    [1]
    단축키 운영진에게 바란다(삭제요청/제안) 운영게 게시판신청 자료창고 보류 개인정보취급방침 청소년보호정책 모바일홈