메모리 동적 할당

메모리 정/동적 할당의 개념과 동적할당함수의 기능과 사용법, 메모리 관리 함수.

  • 학습 목표
    1. 메모리 정적할당과 동적할당의 이해.
    2. 메모리 동적할당함수를 이용하여 프로그램 작성.
    3. 메모리 관리함수의 기능 이해.

주요 용어

  • 데이터 영역 : 전역변수와 static 변수가 저장되는 기억공간 영역.
  • 힙(heap) 영역 : 프로그래머의 필요에 의해 할당과 소멸이 이루어지는 기억공간 영역.
  • 스택(stack) 영역 : 지역변수와 매개변수가 저장되는 기억공간 영역.
  • 메모리 정적할당 : 프로그램이 작성되는 단계에서 기억공간의 크기가 결정되는 기억공간 확보방법.
  • 메모리 동적할당 : 프로그램이 실행되는 중에 입력되는 자료에 따라 기억공간의 크기를 결정할 수 있는 기억공간 확보방법.

메모리 동적할당의 개념

C 언어에서의 기억공간?

  • 프로그램의 실행을 위해 기억공간 필요.
  • 기억공간은 운영체제에서 할당.
  • 할당되는 기억공간의 영역.
    • 데이터 영역.
      • 전역변수와 static 변수가 저장되는 영역.
      • 프로그램이 시작하면서 할당되고, 종료하면 소멸하게 됨.
    • 힙 영역
      • 개발자의 필요에 의해 할당/소멸이 이루어지는 영역.
      • 프로그램이 실행되는 중에 크기가 변함.
      • 메모리 동적 할당에 사용되는 영역.
    • 스택 영역
      • 지역변수와 매개변수가 저장되는 영역.
      • 함수 호출이 완료되면 사라짐.

기억공간의 확보

메모리 정적 할당(Static Allocation)

  • 기억공간의 데이터 영역스택 영역 이용.
  • 프로그램을 작성하는 단계에서 필요한 기억공간의 크기를 결정.

메모리 동적 할장(Dynamic Allocation)

  • 기억공간의 힙 영역 이용.
  • 프로그램 실행 중에 입력되는 자료에 맞게끔 기억공간의 크기를 결정.

메모리 정적할당

  • 변수 선언이나 배열 선언과 같이 프로그램을 작성하는 단계에서 필요한 기억 공간의 크기를 결정.
    • 변수 선언과 같이 할당 시켜줘야 할 기억공간의 한계 크기를 명확히 알고 있을 경우 사용.
    • 메모리 정적 할당은 프로그램이 시작될 때 미리 기억공간의 크기를 고정하여 할당.

메모리 정적할당의 예

  #include <stdio.h>

  void test1(int);
  void test2(int);

  //  전역변수로 선언되어 데이터 영역에 할당.
  //  프로그램 종료될 때까지 존재.
  int a = 100;

  void main()
  {
    //  지역변수로 스택 영역에 할당.
    //  main()가 종료될 때까지 존재.
    int b = a;

    test1(b);
    test2(b);
  }

  //  test1이 호출되면,
  //  매개변수 c와 지역변수 d는 스택영역에 할당.
  //  test1이 종료되면 c, d는 지워짐.
  void test1(int c)
  {
    int d;
    d = c + 10;
    printf("%d\n", d);
  }

  //  test2가 호출되면,
  //  매개변수 e와 지역변수 f는 스택영역에 할당.
  //  종료되면 d, f는 지워짐.
  void test2(int e)
  {
    int f;
    f = e + 20;
    printf("%d\n", f);
  }

  //  main()가 종료되면 스택영역에 할당된 b도 제거.
  //  프로그램이 끝아면 a도 제거.

메모리 정적할당의 장/단점

  • 장점
    • 프로그램에서 사용하게 될 변수의 기억 공간의 크기를 명확히 알고 있다면,
      메모리 정정할당은 쉽게 기억 공간을 사용할 수 있고, 에러의 발생 확률을 줄일 수 있음.
  • 단점
    • 사용하게 될 기억 공간의 크기를 정확히 알지 못하거나, 사용되는 자료의 크기가 각각 차이가 심하다면,
      기억공간의 낭비를 가져오게 됨.

메모리 정적할당의 문제점

  #include <stdio.h>

  void main()
  {
    int size;
    //  배열의 크기를 변수로 선언하면 에러 발생?
    char a[size];

    printf("입력할 문자열의 크기? : ");
    scanf("%d", &size);

    printf("주소 : ");
    scanf("%s", a);

    printf("입력된 주소 %s\n", a);
  }
  #include <stdio.h>
  #include <stdlib.h>

  void main()
  {
    int size;
    char *a;

    printf("입력할 문자열의 크기? : ");
    scanf("%d", &size);

    //  메모리 동적할당.
    a = (char *)malloc(sizeof(char) * size);
    printf("주소 : ");
    scanf("%s", a);

    printf("입력된 주소 %s\n", a);
    free(a);
  }

메모리 동적할당 함수

malloc(), calloc(), realloc(), free() 등

메모리 동적할당의 장/단점

  • 힙 영역을 이용하여 프로그램 실행 중에 입력되는 자료의 크기에 맞게 기억 공간 확보.
  • 많은 자료를 처리하는 배열의 크기를 실행 시간에 정의해야 하는 경우에 유용.
  • 프로그램 실행 시 기억 공간의 크기를 지정/재조정 가능.
  • 시간이 지체되는 단점.

메모리 동적할당 순서

  • 기억공간을 동적으로 할당 받을 변수를 포인터를 이용하여 선언.
  • malloc() 등을 이용하여 기억공간을 동적으로 할당 가능.
  • 기억공간의 사용이 끝나면 free()를 이용하여 기억공간 해제.

malloc()

  • 인자로 할당 받고자 하는 기억 공간의 크기를 byte 단위로 전달.
  • 힙 영역에 그 크기만큼 기억 공간을 할당, 할당한 기억공간의 첫 번째 주소 반환.
  • void*로 명시하여 어떤 형이든 형 변환 가능.
  • 초기화 안됨(기억공간의 초기화를 위해서는 memset() 사용).
  • 형식 : void * malloc(size_t, number_of_bytes);
  • 기능 : number_of_bytes에서 주어지는 크기만큼 기억 공간을 동적으로 할당.
  • 예 : void * malloc(sizeof(int));

free()

  • 메모리 해제 함수.
    • 힙 영역에 할당된 공간은 프로그램이 종료될 때까지 유지됨.
    • 할당된 기억 공간을 해제하지 않으면, 공간 부족 현상 발생.
    • 명시적인 반남.
  • 형식 : void free(void *p);
  • 기능 : 동적으로 할당된 기억 공간을 해제할 때 사용.

메모리 동적할당 예 - 1

  #include <stdio.h>
  #include <stdlib.h>

  void main()
  {
    //  1) 동적할당을 위한 포인터변수 선언.
    int *a;
    //  2) 기억공간 할당,
    //    - (int *)는 왼쪽의 포인터변수 a와 자료형을 일치시키기 위한
    //      강제 형변환.
    a = (int *)malloc(sizeof(int));

    if (a == NULL)
    {
      puts("FAILLURE OF ALLOCATION!");
      exit(1);
    }

    *a = 20;
    printf("VARIABLE a : %d\n", *a);
    //  3) 할당받은 기억공간 해제.
    free(a);
  }

메모리 동적할당 예 - 2

  #include <stdio.h>
  #include <stdlib.h>
  #pragma warning(disable : 4996)

  void main()
  {
    //  입력받을 문자 수 저장 변수 선언.
    int size;
    // 1) 동적 할당된 기억공간을 연결할 포인터.
    char *str;

    printf("INSERT SIZE OF STRING : ");
    scanf("%d", &size);

    // 2) 입력 받을 문자 수(size + 1)에 맞게 동적 할당.
    str = (char *)malloc(size + 1);

    if (str == NULL)
    {
      puts("FAILLURE OF ALLOCATION!");
      exit(1);
    }

    printf("INSERT STRING : ");
    // 동적으로 할당된 기억공간에 문자열 저장.
    scanf("%s", str);

    printf("STRING THAT SAVED AT DYNAMIC MEMORY : \n%s\n", str);

    // 3) 할당받은 기억공간 해제.
    free(str);
  }

calloc()

  • malloc()와 동일하게 힙 영역에 기억공간 할당.
  • 사용하는 형태와 할당된 기억 공간을 0으로 초기화.
  • 형식 : void * calloc( int n, int size );
  • 기능 : 주어진 size의 크기를 갖는 기억 공간 n개를 할당.
  • 예 : void * calloc( n, sizeof(int));
  #include <stdio.h>
  #include <stdlib.h>

  void main()
  {
    int i;
    int *a;

    // int형 크기의 기억공간 5개 할당.
    a = (int *)calloc(5, sizeof(int));

    for (i = 0; i < 5; i++)
    {
      //  0으로 초기화 되어 있음.
      printf("%d\n", a[i]);
    }

    free(a);
  }

realloc()

  • 이미 할당 받은 기억 공간의 크기를 변경해야 할 필요가 있을 때 사용.
  • 형식 : void * realloc( void *p, int size);
  • 기능 : 포인터 p가 가리키고 있는 기억공간의 크기를 지정된 size의 크기로 변경.
  int *a;
  //  int형 크기의 5개 기억공간 할당.
  a = (int *)calloc(5, sizefo(int));
  ...
  //  int형 크기의 10개 기억공간 재할당.
  a = (int *) realloc(a, 10 * sizeof(int));

기억공간 관리함수

memcmp(), memcpy(), memset()

memcmp()

  • 기억 공간에 들어 있는 자료를 주어지는 크기만큼 비교하여, 같은지 여부를 알 수 있게 해주는 함수.
  • 형식 : int memcmp( void *s1, void *s2, size_t n);
  • 기능 : s1, s2가 가리키고 있는 기억 공간의 내용을 n byte 만큼 비교.
    • n바이트만큼 비교하여 s1 > s2 면 양수, s1 < s2 면 음수, s1 == s2 면 0 반환.
  #include <stdio.h>
  //  기억공간 관리함수를 위한 헤더파일.
  // #include <mem.h>
  #include <memory.h>

  void main() {
    char *s1 = "aaa";
    char *s2 = "bbb";

    int stat;

    stat = memcmp(s1, s2, 3);

    printf("%d\n", stat);
  }

memcpy()

  • 기억 공간의 자료를 다른 기억 공간 영역으로 복사하기 위한 함수.
  • 형식 : void * memcpy( void *dest, const void * src, size_t n);
  • 기능 : src에서 n byte만큼 dest에 복사.
  #include <stdio.h>
  #include <memory.h>
  #include <string.h>

  void main()
  {
    char src[] = "1234567890";
    char dest[] = "abcdefghijklmnopqrstuvwxyz";
    char *stat;

    printf("BEFORE MEMCPY() DEST : %s\n", dest);

    //  src의 첫 부분에서부터 문자열의 길이(strlen())만큼의 자료를 dest에 복사.
    stat = (char *)memcpy(dest, src, strlen(src));

    if (stat)
      printf("AFTER MEMCPY() DEST : %s\n", dest);
    else
      printf("FAILURE ON MEMCPY()!");
  }
  //  BEFORE MEMCPY() DEST : abcdefghijklmnopqrstuvwxyz
  //  AFTER MEMCPY() DEST : 1234567890klmnopqrstuvwxyz

memset()

  • 기억 공간의 자료를 지정한 문자로 채우는 함수.
  • 할당된 기억 공간의 초기화나 내용 삭제를 위해 주로 사용.
  • 형식 : void * memset( void *s, int c, size_t n );
  • 기능 : 포인터 s가 가리키는 곳을 c 값으로 n byte 만큼 채운다.
  #include <stdio.h>
  #include <memory.h>
  #include <string.h>

  void main()
  {
    char s[] = "1234567890";

    printf("BEFORE MEMSET() : %s\n", s);

    //  배열 s의 데이커를 *로 길이 만큼 채움.
    memset(s, '*', strlen(s));

    printf("AFTER MEMSET() : %s\n", s);
  }

728x90
반응형

'Language > C' 카테고리의 다른 글

[C] 파일 처리 함수 - 2  (0) 2021.01.02
[C] 파일 처리 함수 - 1  (0) 2021.01.01
[C] 구조체와 공용체 - 2  (0) 2021.01.01
[C] 구조체와 공용체 -1  (0) 2020.12.27
[C] 배열과 포인터 - 3  (0) 2020.12.27

파일 처리 함수 - 2

순차파일 입출력함수와 랜덤파일 입출력함수, 랜덤파일의 위치제어.

  • 학습 목표
    1. 순차파일을 만들고 읽기.
    2. 랜덤파일 만들고 읽기.
    3. 랜덤파일의 위치 제어.

주요 용어

  • 레코드(record) : 파일을 구성하는 논리적인 기본 단위.
  • 텍스트 모드(textmode) : \n과 CR/LF 사이의 변환과정을 거치는 파일 모드.
  • 2진 모드(binary mode) : \n과 CR/LF 사이의 변환과정 없는 파일 모드.
  • 랜덤파일의 위치제어 : fseek()를 사용하여 랜덤파일의 특정부분을 입출력하는 것..

순차파일 입출력 함수

순차파일 출력함수

만들어진 파일에 자료를 기록하는 함수.

  • putc(), fputc(), fputs(), fprintf()

putc()

  • 문자 단위의 파일 출력함수.
  • fputc()와 유사.
  • 형식 : putc(문자변수, 파일포인터변수);
  • 사용 예 : putc(c, fp);
  • 기능 : fp가 가리키는 파일에 변수 c에 있는 문자 출력.
  #include <stdio.h>
  #include <stdlib.h>

  void main()
  {
    //  파일 포인터 선언
    FILE *fp;
    char c;

    // 파일 생성이므로 텍스트 쓰기모드로 오픈.
    fp = fopen("putc.tt.txt", "w");

    //  파일 개방 여부 체크. -> 에러메세지와 프로그램 종료.
    if (fp == NULL)
    {
      printf("FAIL TO OPEN FILE");
      exit(1);
    }

    //  문자 출력의 끝 확인.
    while ((c = getchar()) != EOF)
    {
      // 문자를 파일로 출력.
      putc(c, fp);
    }

    printf("END OF WHILE!");
    fclose(fp);
  }

fputs()

  • 문자열을 파일로 출력.
  • 형식 : fputs(문자열변수, 파일포인터변수);
  • 사용 예 : fputs(s, fp);
  • 기능 : 지정된 파일에 문자열(하나의 레코드) 출력.
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>

  void main() {
    char name[64];
    FILE *fp;
    //  텍스트 쓰기모드 개방하고, 에러시 프로그램 종료.
    if ((fp = fopen("02_fputs.tt.txt", "w")) == NULL) {
      puts("CAN NOT OPEN FILE");
      exit(1);
    }

    gets(name);
    while (strcmp(name, "end")) {
      // 하나의 문자열에 개행문자 추가.
      strcat(name, "\n");
      // 문자열을 fp가 가르키는 파일에 수록.
      fputs(name, fp);
      gets(name);
    }

    printf("BYE!\n");
    // 파일 닫기.
    fclose(fp);
  }

fprintf()

  • 지정된 형식을 가지로 파일에 자료를 출력.
  • 여러 항목의 복합적인 자료로 구성된 레코드를 저장할 때 유용.
  • 형식 : fprintf(파일포인터변수, "출력형식", 변수);
  • 사용 예 : fprintf(fp, "%s %d\n", a, b);
  • 기능 : 지정된 형식대로 자료를 파일포인터 변수가 가리키는 곳에 출력.
  #include <stdio.h>
  #include <stdlib.h>

  void main()
  {
    FILE *fp;
    char no[10], name[10];
    int mid, term, rep, att, i;

    if ((fp = fopen("03_fprintf.tt.txt", "w")) == NULL)
    {
      puts("CAN NOT OPEN FILE");
      exit(1);
    }

    //  stdout : 모니터를 가리키는 특수한 파일포인터.
    fprintf(stdout, "insert no name mid term rep att.");

    for (i = 0; i < 5; ++i)
    {
      scanf("%s %s %d %d %d %d", no, name, &mid, &term, &rep, &att);
      // 지정된 형식으로 자료를 파일에 출력.
      fprintf(fp, "%10s %8s %3d %3d %3d %3d\n", no, name, mid, term, rep, att);
    }

    printf("BYE!\n");
    // 파일 닫기.
    fclose(fp);
  }

C 언어에서 입출력 장치를 파일 개념으로 처리

  • 자동적으로 3개의 표준 파일에 대한 포인터를 생성함.
  • 이러한 표준 파일에 대해서는 다로 파일포인터를 선언할 필요가 없음.
표준파일 파일 포인터 대응 장치
입력 stdin 키보드
출력 stdout 모니터
에러 stderr 모니터

순차파일 입력함수

파일 출력함수에 의해 만들어진 순차파일의 저장된 자료를 읽어내는 함수.
자료를 읽을 때는 파일의 끝에 있는 EOF 신호를 만날 때까지 읽을 수 있는 프로그램 작성.

  • getc(), fgetc(), fgets(), fscanf()

getc()

  • 문자 단위의 파일 입력함수.
  • fgetc() 함수와 유사.
  • 형식 : getc(파일포인터변수);
  • 사용예 : c = getc(fp);
  • 기능 : 지정된 파일로부터 한 문자를 읽어온다.
  #include <stdio.h>
  #include <stdlib.h>

  void main() {
    FILE *fp;
    char c;

    if ((fp = fopen("01_putc.tt.txt", "r")) == NULL) {
      puts("\n\nCAN NOT OPEN FILE");
      exit(1);
    }

    while ((c = getc(fp)) != EOF) {
      putchar(c);
    }

    printf("\n\nBYE!\n");
    // 파일 닫기.
    fclose(fp);
  }

fgets()

  • 파일에 저장된 문자열 자료를 읽을 때 사용.
  • 읽어 낼 문자열의 길이를 반드시 명시.
  • 형식 : fget(문자열변수, 문자열 길이 + 1, 파일포인터 편수);
  • 사용 예 : fget(s, 40, fp);
  • 기능 : 지정된 파일로부터 해당 문자열 길이 만큼의 문자를 읽어 문자열 변수에 저장한다.
  #include <stdio.h>
  #include <stdlib.h>

  void main() {
    char name[20];
    FILE *fp;

    if ((fp = fopen("02_fputs.tt.txt", "r")) == NULL) {
      puts("\n\nCAN NOT OPEN FILE");
      exit(1);
    }

    //  파일의 끝에 도달할 때까지 읽기.
    while (fgets(name, 20, fp) != NULL) {
      printf("%s", name);
    }

    printf("\n\nBYE!\n");
    // 파일 닫기.
    fclose(fp);
  }

scanf()

  • 숫자, 문자 등 복합적인 자료로 구성된 레코드를 읽을 때 사용.
  • 일반적으로 파일의 끝을 판별하는 feof()와 같이 사용.
  • 형식 : fscanf(파일포인터변수, "입력형식", 변수);
  • 사용 예 : fscanf(sp, "%s %d", &a, &b);
  • 기능 : 파일 포인터가 가리키는 곳으로부터 지정된 형식대로 자료를 읽어온다.
  #include <stdio.h>
  #include <stdlib.h>

  void main() {
    FILE *fp;
    char no[10], name[10];
    int mid, term, rep, att;

    if ((fp = fopen("03_fprintf.tt.txt", "r")) == NULL) {
      puts("\n\nCAN NOT OPEN FILE");
      exit(1);
    }

    printf("no name mid, term, rep, att\n");

    //  파일의 끝인지 확인하는 feof()
    while (!feof(fp)) {
      //  파일에 저장된 자료의 형식에 맞게 입력형식을 지정해야 함.
      fscanf(fp, "%10s %8s %3d %3d %3d %3d\n", no, name, &mid, &term, &rep, &att);
      printf("%-10s %-8s %4d %4d %4d %4d\n", no, name, mid, term, rep, att);
    }

    printf("\n\nBYE!\n");
    // 파일 닫기.
    fclose(fp);
  }

레코드 추가를 위한 사용 모드

a a+ ab ab+

  • 형식 : fp = fopen("파일명", "a");
  • 사용 예 : fp = fopen("파일명", "a");
  • 기능 : 이미 만들어진 순차파일의 끝에 새로운 레코드 추가(append).
  #include <stdio.h>

  void main() {
    FILE *fp;
    //  레코드 추가 모드로 파일 개방.
    fp = fopen("04_tt.dat", "a");
    //  파일이 없으르모 새 파일 생성 후 새 내용 기록.
    fputs("asdf \n", fp);
    fputs("qwer \n", fp);
    fputs("zxcv \n", fp);
    fputs("qaz \n", fp);
    fputs("wsx \n", fp);

    fclose(fp);
  }

랜덤파일 처리 (random file)

  • 파일의 임의의 위치에서 자료를 읽거나 쓸 수 있음.

  • 레코드의 길이가 일정함.

  • 순차파일에 비해

    • 장점 : 레코드 탐색이 빠르고 효과적.
    • 단점 : 기억공간 낭비.

랜덤파일 열기

일반적으로 랜덤파일을 입출력할 때는 2진 모드로 파일을 개방.

  • 2진 모드의 특징
    • 텍스트 파일보다 적은 기억공간.
    • 레코드의 길이를 개발자가 결정.
    • 파일 포인터의 위치 변경 가능.

랜덤파일 입출력 함수

fwrite()

  • 레코드의 길이를 지정.
  • 자료저장 변수는 포인터 형.
  • 형식 : fwirte(저장자료변수, 레코드길이, 레코드개수, 파일포인터);
  • 사용 예 : fwrite(name, 10, 1, fp);
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>

  void main()
  {
    FILE *fp;
    char name[10];

    //  2진 파일 쓰기 모드 개방.
    if ((fp = fopen("08_fwrite.dat", "wb")) == NULL)
    {
      puts("\n\nCAN NOT OPEN FILE");
      exit(1);
    }

    gets(name);

    while (strcmp(name, "END"))
    {
      //  2진 파일 쓰기.
      fwrite(name, 10, 1, fp);
      gets(name);
    }

    fclose(fp);
  }

fread()

  • 읽기에 성공하면 읽은 레코드 수를 리턴.
  • 형식 : fread(읽을자료변수, 레코드길이, 레코드개수, 파일포인터);
  • ex : fread(name, 10, 2, fp);
  #include <stdio.h>
  #include <stdlib.h>

  void main() {
    FILE *fp;
    char name[10];

    //  2진 파일 읽기 모드 개방.
    if ((fp = fopen("08_fwrite.dat", "rb")) == NULL) {
      puts("\n\nCAN NOT OPEN FILE");
      exit(1);
    }

    while (1) {
      //  레코드의 개수가 1이 아닌 값이 리턴되면 파일은 끝난다.
      if (fread(name, 10, 1, fp) != 1)
        break;

      puts(name);
    }

    fclose(fp);
  }

랜덤파일 위치 제어

레코드의 길이가 일정하기 때문에, 자료의 위치를 제어할 수 있음.

fseek()

  • 파일 포인터를 임의의 위치로 이동시키는 함수.
  • 랜덤파일의 특정부분을 입출력 할 수 있음.
  • 형식 : fseek(파일포인터_변수, 이동할_상대위치, 기준위치를_지정하는*모드);
  • ex : fseek( fp, 2 * REC_size, SEEK_SET );

기준위치 지정모드

stdio.h에 정의됨

기준위치모드 동일기호 설명
0 SEEK_SET 파일의 시작위치
1 SEEK_CUR 현재 파일포인터의 위치
2 SEEK_END 파일의 끝 위치

 

  #include <stdio.h>
  #include <string.h>

  void main()
  {
    char str[10];
    FILE *fp = fopen("sample6.txt", "wt");

    fputs("1234567890", fp);
    fclose(fp);

    fp = fopen("sample6.txt", "rt");
    fseek(fp, 7, SEEK_SET);
    fgets(str, 4, fp);
    printf("print 3 str from 7 : %s\n", str);
    // 890

    fseek(fp, -2, SEEK_CUR);
    fgets(str, 3, fp);
    printf("print 2 char before 2 char cur loc : %s\n", str);
    // 90

    fseek(fp, -9, SEEK_END);
    fgets(str, 6, fp);
    printf("print 5 str from 9 char before last : %s\n", str);
    // 23456

    fclose(fp);
  }

728x90
반응형

'Language > C' 카테고리의 다른 글

[C] 메모리 동적 할당  (0) 2021.01.03
[C] 파일 처리 함수 - 1  (0) 2021.01.01
[C] 구조체와 공용체 - 2  (0) 2021.01.01
[C] 구조체와 공용체 -1  (0) 2020.12.27
[C] 배열과 포인터 - 3  (0) 2020.12.27

파일 처리 함수 - 1

자료의 입출력 개념과 파일 입출력의 개념. 파일 포인터와 순차파일.

  • 학습 목표
    1. 파일을 이용한 자료의 입출력 이해.
    2. 파일 입출력의 수행과정 이해.
    3. 파일 포인터를 이용한 자료의 입출력 수행.
    4. 순차파일의 개념 이해.

주요 용어

  • 스트림(stream) : 자료의 입출력을 위한 논리적인 통로.
  • 파일 포인터 : 파일이 어디 있는지를 가리키는 포인터.
  • 순차파일 : 파일의 처음에서부터 자료를 차례로 읽고, 기록하는 파일.
  • 랜덤파일 : 파일의 임의의 위치에서 자료를 읽고, 기록하는 파일.

파일 입출력의 개념

  • 보조기억장치의 파일을 이용한 자료의 입출력.
    • 파일 처리함수를 이용.
    • 표준입출력 -> 키보드나 모니터를 통한 입출력.
  • 파일 처리 함수.
    • 보조기억장치에 들어있는 정보들의 모임을 파일이라 하고, 이러한 파일을 제어하는 함수.

파일

  • 보조기억장치에 저장된 데이터들의 모임.
  • 일련의 byte들로 구성.
  • C 프로그램은 운영체제를 통해서 파일을 읽거나 씀.
  • C 언어에서는 컴퓨터와 연결된 장치들 까지도 모두 파일의 범주에 넣어 처리.

파일 구분

  • 텍스트 파일(text file)
    • 화면에 출력되는 문자들로 구성된 파일.
  • 2진 파일(binary file)
    • 텍스트 파일을 포함한 모든 종류의 자료를 다루는 파일.
    • 컴파일 되어 있어 기계어에 가까우므로 내용을 이해하거나 인쇄 불가능.

파일에 대한 자료의 입출력

  • 파일 입력
    • 디스크 상의 특정 위치(파일)에 수록되어 있는 자료를 읽어들여 기억공간에 수록하는 절차.
  • 파일 출력
    • 기억공간에 있는 자료를 디스크상의 특정위치(파일)에 수록하는 절차.
  • 파일포인터를 사용하여 파일 입출력 수행.

파일처리를 위해서는 파일포인터를 사용

  • 파일포인터
    • 파일이 어디에 있는지를 가리키는 포인터.
    • 모든 파일 입출력 함수는 파일 포인터를 사용

파일을 입출력 할 때 버퍼(buffer) 사용

  • 기억공간과 디스크 사이에 존재하는 임시 기억 공간.
  • 사용
    • 파일 입출력 시 디스크에 저장된 자료를 기억공간으로 읽어 들일 때.
    • 기억 공간에서 처리된 자료를 디스크에 저장할 때.

파일포인터를 이용한 파일 입출력

자료의 입출력 개념

  • 프로그램과 입출력 장치(콘솔, 파일, 소켓등)와의 사잉에 이루어 지는 자료의 입력과 출력.
  • 자료의 입출력을 위한 논리넉인 통로 : 스트림

스트림 (stream)

stream

  • 표준 입출력장치를 이용한 자료 입출력.
    • 표준 입출력장치와의 스트림은 프로그램 실행/종료 시
      자동으로 생성/소멸 됨.
  • 파일 입출력을 위한 스트림은 프로그램을 통해 생성/소멸 시켜주어야 함.

파일 입출력의 수행 과정

  • 과정

    1. 파일을 연다.
      • 파일과 자료를 주고 받을 수 있는 스트림을 생성(fopen() 사용).
    2. 입출력을 수행한다.
    3. 파일을 닫는다.
  • 생성된 스트림을 소멸시키기 위한 과정(fclose() 사용).

스트림(stream)의 생성

  • 파일과 프로그램과의 통로(논리적인 접속)를 구성.
  • 통로 역할을 파일포인터가 수행.

파일입출력 프로그램 구조

  // 파일을 가리키는 파일포인터 선언.
  FILE *fp;

  //  파일 열기 : 지정한 모드로 열고, fp로 하여금 파일을 가리키게 함.
  fp = fopen("파일명", "모드");

  //  입출력 수행 : 파일처리함수와 fp를 이용하여 입출력 수행.
  ...

  //  파일 닫기 : 버퍼를 비우고 fp가 가리키는 파일을 닫음.
  fclose(fp);
  #include <stdio.h>

  void main() {
    char ch;
    FILE *fp;
    fp = fopen("file_IO_test.txt", "W");
    for (ch = 'A'; ch <= 'Z'; ch++)
      fputc(ch, fp);

    fclose(fp);
  }

파일처리 함수와 기능

function desc
fopen("filename", "mode") 파일을 지정된 모드로 열기
fclose() 파일 닫기
fget(), getc() 파일로부터 한 문자 읽기
fputc(), putc() 파일에 한 문자 쓰기
fgets() 파일로부터 문자열 읽기
fputs() 파일에 문자열 쓰기
fscanf() 파일로 부터 정해진 형식에 따라 읽기
fprintf() 파일에 정해진 형식에 따라 쓰기
fread() 파일로부터 정해진 크기의 자료를 정해진 개수만큼 읽기
fwrite() 파일에 정해진 크기의 자료를 정해진 개수만큼 쓰기
fseek() 파일에서 입출력 위치 이동
feof() 파일의 끝인가를 판별
ferror() 파일의 입출력 시 에러 발생 유무 조사

파일포인터 선언과 파일 열기

파일포인터 선언

  • 파일 입출력을 위해 파일포인터 선언.
  • 실제 파일과 프로그램을 연결해주는 통로가 됨.
  • 형식 : FILE *변수명;
  • 사용 예 : FILE *fp;
  • 기능 : 파일형 포인터변수를 선언.

파일포인터 변수와 버퍼의 관계

  • FILE형 : 구조체형.
  • FILE형 포인터 변수 : 파일에 대한 여러가지 정보를 가진 변수.

file 형 포인터 변수

 

파일 열기 : fopen()

프로그램과 디스크 상의 파일 사이에 데이터가 입출력할 수 있도록 통로를 만들어 주는 것.

  • 형식 : fopen("파일명", "사용모드");
  • 사용 예 : fp = fopen("test.dat", "r");
  • 기능 : 파일을 열어 사용할 수 있게 함.
  • 입출력이 정상이면 지정된 파일의 파일포인터에 시작주소 값을 리턴.
  • 파일이 개방되지 않을 때는 에러 값(NULL값) 리턴.
  • 파일 명
    • 경로를 포함 할수도 안 할 수도 있다?
  • 사용 모드
    • 개방한 파일의 용도를 결정.
    • 자료의 입출력 방식을 의미
    • 사용(개방)모드 = 파일 접근 모드 + 데이터 입출력 모드.
      • r, r+ : 읽기
      • w, w+ : 쓰기
      • a, a+ : 추가
      • t : 텍스트 모드(text mode)
        • 기본 값.
        • 프로그램에서 파일로 자료를 입출력할 때 변환이 일어나는 입출력 모드.
        • 문자 변환이 필요(\n -> CR/LF).
      • b : 2진 모드(bianry mode)
        • 변환이 일어나지 않는 입출력 모드.
        • 문자 변환 불필요.
사용 모드 의미 파일이 있을 경우 파일이 없을 경우
r, rb 읽기 정상처리 NULL
r+, rb+ 읽기/쓰기 정상처리 NULL
w, wb 쓰기 이전 내용 삭제 새 파일 생성
w+, wb+ 읽기/쓰기 이전 내용 삭제 새 파일 생성
a, ab 추가 이전 내용 뒤에 추가 새 파일 생성
a+, ab+ 읽기/추가 이전 내용 뒤에 추가 새 파일 생성
  fopen("filename", "w") //  텍스트 출력 모드
  fopen("filename", "rt") //  텍스트 입력 모드
  fopen("filename", "wb") //  2진 출력 모드
  fopen("filename", "rb+") //  2인 입력 모드

파일 닫기 fclose()

  • 형식 : fclose(파일포인터 변수);
  • 사용 예 : fclose(fp);
  • 기능 : 열었던 파일을 닫고, fp 해제.
  • 개방된 통로와 버퍼를 원 상태로 환원.
  • 쓰기의 경우 파일 끝에 EOF(End Of File) 신호 부가(완전한 파일로 완성됨).

파일 열기와 닫기 사용 예

  FILE *fp1, fp2;
  //  a파일을 쓰기용으로 열어 그 시작주소를 파일포인터 fp1에게 부여.
  fp1 = fopen("a", "w");
  fp2 = fopen("b", "r");

  //  파일 open이 안된 경우 종료 해야 함.
  if( (fp = fopen("filename", "r") ) == NULL ) {
    exit(1);  //  프로그램 종료
  }

  //  열었던 파일을 닫고 파일포인터 해제.
  fclose(fp1);
  fclose(fp2);

순차파일처리

정보의 집합 => 파일 => 레코드 단위 구성

  • 레코드
    • 파일 입출력 처리에 사용되는 논리적인 기본 단위.
    • 각 레코드들은 필드(field)들로 구성.

파일 처리 함수를 이용하여 파일을 편성하는 방법에 따라 순차파일, 랜덤파일로 구분.

파일의 종류

순차 파일 (sequential file)

  • 파일의 처음부터 자료를 차례로 읽고, 기록하는 파일.
  • 레코드의 길이가 일정하지 않은 파일.

랜덤 파일 (random file)

  • 파일의 임의의 위치에서 자료를 읽고, 기록하는 파일.
  • 레코드의 길이가 일정한 파일.

순차파일에서 레코드 구성

순차파일은 레코드의 길이가 일정하지 않기 때문에 레코드들의 구분이 필요 : CR/LF를 사용하여 구뷴

 

순차파일 출력함수

만들어진 파일에 자료를 기록하는 함수.

  • putc(), fputc(), fputs(), fprintf()
  • 순차파일 출력함수
    • getc(), fgetc(), fgets(), fscanf()

728x90
반응형

'Language > C' 카테고리의 다른 글

[C] 메모리 동적 할당  (0) 2021.01.03
[C] 파일 처리 함수 - 2  (0) 2021.01.02
[C] 구조체와 공용체 - 2  (0) 2021.01.01
[C] 구조체와 공용체 -1  (0) 2020.12.27
[C] 배열과 포인터 - 3  (0) 2020.12.27

구조체와 공용체 - 2

함수와 구조체, typedef, 구조체 비트필드, 공용체.

  • 학습 목표
    1. 구조체를 이용한 매개변수사이의 자료전달 방법 이해.
    2. typedef를 이용하여 새로운 자료형 정의.
    3. 구조체 비트필드를 선언 및 사용.
    4. 공용체 사용.

주요 용어

  • typedef : 이미 존재하는 자료형에 새로운 이ㅁ을 부여하기 위한 키워드.
  • 구조체 비트필드 : 주기억장치의 기억공간을 byte 단위가 아닌 bit 단위로 사용하는 방법.
  • 공용체 : 동일한 기억장소에 여러 유형의 자료를 저장하기 위해 정의하는 자료형.

함수와 구조체

함수에서의 구조체 사용

구조체를 함수의 매개변수로 사용

  • 일반 변수를 함수의 매개변수로 사용하는 것과 동일.

  • 매개변수가 구조체인 경우 함수의 형식매개변수를 구조체로 선언.

  • 해당 구조체 전체가 복사되기 때문에 편리.

  • 구조체 전체가 복사되기 때문에 시간이 많이 걸리고, 기억공간의 낭비가 심함.

    • #include <stdio.h>
      
      //  함수의 원형 정의 -> struct -> int나 char와 같은 일종의 자료형.
      struct num calc(struct num); 
      struct num
      {
        int x, y, sum, mul;
      };
      
      void main()
      {
        // 구조체 변수 선언.
        struct num num1;
        num1.x = 10;
        num1.y = 20;
      
        //  피호출함수 calc()에 struct num형 구조체를 매개변수로 넘김.
        num1 = calc(num1);
      
        printf("x : %d, y : %d, sum : %d, mul : %d\n", num1.x, num1.y, num1.sum, num1.mul);
      }
      
      //  넘겨받은 struct num형 구조체의 멤버끼리 연산, 구조체를 리턴함
      struct num calc(struct num num)
      {
        num.sum = num.x + num.y;
        num.mul = num.x * num.y;
        return num;
      }

구조체 포인터를 함수의 매개변수로 사용

  • 일반적으로 구조체 포인터를 함수의 매개변수로 사용.

  • 구조체를 복사하지 않기 때문에 실행속도가 향상, 기억공간의 사용 효율 증가.

    • #include <stdio.h>
      
      struct num calc(struct num *);
      struct num
      {
        int x, y, sum, mul;
      };
      
      void main()
      {
        // 구조체 변수 선언.
        struct num num1;
        num1.x = 10;
        num1.y = 20;
      
        // 참조호출 & 사용.
        num1 = calc(&num1);
      
        printf("x : %d, y : %d, sum : %d, mul : %d\n", num1.x, num1.y, num1.sum, num1.mul);
      }
      
      // 구조체포인터를 매개변수로 넘겨받음.
      struct num calc(struct num *num)
      {
        num->sum = num->x + num->y;
        num->mul = num->x * num->y;
      }

typedef

이미 존재하는 자료형에 새로운 이름은 붙이기 위한 키워드.

  • 간단하거나 의미있는 이름으로 바꿀 수 있어 프로그램 이해가 쉽다.

  • 구조체 형을 선언하는데 많이 사용.

  • 형식

    • typedef 기존_자료형 새로운_자료형_이름;
    • typedef int INT;

    •   //  unsigned int 형을 BYTE라는 이름으로 정의.
        typedef unsignd int BYTE; 
        //  컴파일러가 unsigned int val로 해석
        BYTE val;
      
        //  int *를 PTR로 재정의.
        typedef int * PTR;
        //  int *p1, *p2를 의미.
        PTR p1, p2;
    •   #include <stdio.h>
      
        struct data {
          int x, y;
        };
      
        //  data형 구조체를 새로운 이름 DATA로 정의.
        typedef struct data DATA;
      
        void main() {
          //  struct data d = {1, 2}; // ->
          DATA d = {1, 2};
      
          printf("d.x : %d, d.y : %d\n", d.x, d.y);
        }

typedef를 이용한 구조체 표현의 다른 방법

  struct data {
    int x, y;
  };

  typedef struct data DATA;

  //   구조체 정의와 typedef 선언을 한번에 표현.
  typedef struct data {
    int x, y;
  } DATA;
  #include <stdio.h>
  #include <string.h>

  struct person {
    char name[20];
    char gender;
    int age;
  };

  // person 형 구조체를 MAN으로 정의.
  typedef struct person MAN;
  // unsigned char를 CHAR로 정의.
  typedef unsigned char CHAR;
  // int *를 PTR로 정의.
  typedef int *PTR;

  void main() {
    //  struct person memb; // ->
    MAN memb;
    // unsigned char data; // ->
    CHAR data;
    // int * pt; // ->
    PTR pt;

    strcpy(memb.name, "ASDF");
    memb.gender = 'F';
    memb.age = 30;

    //  unsignd char data에 100 대입.
    data = 100;
    // person형 구조체의 age값 주소를 int* pt에 대입.
    pt = &(memb.age);

    printf("*pt = %d\n", *pt);
  }

구조체 비트필드(bit field)

  • 주기억장치의 기억공간을 byte 단위가 아닌 bit 단위로 사용
    • 프로그램 시 bit 단위의 연산이 필요할 경우 int 형 변수를 사용.
    • 이때 int형은 4 byte (32 bit)이므로 1 bit를 제외한 32 bit의 기억공간 낭비가 발생함.
  • 구조체 비트필드를 사용하면
    • 기억공간 절약.
    • 융통성 있는 데이터 구조체 생성 가능.

구조체 비트필드의 정의

  struct 비트필드명 {
    자료형 비트필드변수 : 비트크기;
  };

  struct bit_filed {
    unsigned a : 1; // -> 1 bit;
    unsigned g : 2; // -> 2 bit;
  }

구조체 비트필드의 선언 예와 기억공간 구조

  struct tt {
    unsigned short a : 4;
    unsigned short b : 2;
    unsigned short c : 1;
    unsigned short d : 7;
  };
  //  구조체 비트필드 변수의 선언.
  struct tt bit;

 

구조체 비트필드의 기억공간 구조

구조체 비트필드의 참조

  • 비트필드의 자료형은 int나 unsigned로 선언.
  • 비트필드에 대한 포인터나 배열은 사용 안됨.
  • 비트필드의 전체 크기는 시스템이 제공하는 int의 크기 이내여야 함.
  struct tt
  {
    unsigned a : 4;
    unsigned b : 2;
    unsigned c : 1;
    unsigned d : 7;
  };

  struct tt bit;
  //  필드에 값 대입
  bit.a = 15;
  bit.b = 3;
  bit.c = 0;
  bit.d = 127;
  #include <stdio.h>

  void main() {
    //  구조체 비트필드의 정의.
    struct tt {
      unsigned a : 5;
      unsigned b : 6;
      unsigned c : 6;
      unsigned d : 4;
    };

    //  고조체 비트필드 변수의 선언과 초기화.
    struct tt v = {1, 2, 3, 4};

    printf("v : { a : %d, b: %d, c : %d, d : %d }\n", v.a, v.b, v.c, v.d);
    // v : { a : 1, b: 2, c : 3, d : 4 }
    printf("v's usage is %d byte.\n", sizeof(v));
    // v's usage is 4 byte.
  }

구조체 비트필드의 기억공간 구조

  struct tt {
    //  비트필드의 총 수가 int의 크기보다 클 경우 ->
    // 비트필드가 2개의 int 사이에 걸쳐 저장될 수 없다.
    unsigned short a : 5;
    unsigned short b : 6;
    unsigned short c : 6;
    unsigned short d : 4;
  };

 

구조체 비트필드의 기억공간 구조


공용체의 개념

공용체 (union)

  • 동일한 기억장소에 여러 유형의 자료를 저장하기 위해서 프로그래머가 선언한 자료형.
  • 공용체 안에 포한된 자료들이 같은 기억장소를 공유하여 사용.
  • 사용될 자료의 자료형이 유동적일 경우 기억 공간을 효율적으로 사용할 수 있는 장점.

공용체의 예

  • 공용체의 멤버들이 완전히 다른 자료형을 가질 때 기억공간을 절약하기 위해 사용.
  • ex :
    • 급여관리
      • 원화로 월급을 지급받는 사람 : 정수형으로 처리.
      • 달러로 월급을 지급받는 사람 : 실수형으로 처리.
      • 공용체를 사용하면 필요에 따라 메모리의 자료형을 선택해서 값 저장 가능.

공용체 정의

  union 공용체명 {
    field 1;
    field 2;
  }

  union var {
    char a;
    int b;
    float c;
  }

공용체 변수 선언

  • 형식 : union 공용체명 변수명;
  • 사용 예 : unioin var abc;

공용체 졍의와 변수 선언 예

  //  공용체 정의
  union var {
    //  공용체 멤버
    char a, int b, float c;
  };
  //  공용체 변수 선언
  union var abc; 

공용체 변수의 참조 방법

  union var
  {
    char a, int b, float c;
  };
  union var abc;
  // 공용체 변수의 참조
  abc.a = 'A';
  abc.b = 133;
  abc.c = 1234.5678;

공용체의 사용

  • 공용체가 사용 되면
    • 공용체의 멤버 중에서 자료크기(byte 수)가 가장 큰 멤버에 대해서만 기억공간이 할당.
    • 기억 공간의 시작 위치부터 각 부분을 다른 멤버가 공용으로 사용.

공용체 기억공간 표현의 예

  union hold {
    short int digit;
    double big;
    char letter;
  }

 

공용체 기억공간

공용체 변수의 참조 예

  union hold {
    short int digit;
    double big;
    char letter;
  };
  union hold fit; 

  fit.digit = 23;     //  2 byte 사용.
  fit.big = 1234.567; //  23이 지워지고 1234.567 저장 (8 byte 사용)
  fit.letter = 'b';   //  1234.567 삭제, 'b' 저장. (1 byte 사용)

공용체 변수의 기억공간 사용 예

 

공용체 변수의 기억공간 사용 예

 

공용체 변수의 사용 예

  #include <stdio.h>

  void main()
  {
    union tt
    {
      short int i;
      float f;
      double d;
    };
    //  공용체 변수 선언
    union tt t;

    t.i = t.f = t.d = 0;

    printf("%d byte \n", sizeof(t));

    t.i = 100;

    printf("%d %f %f\n", t.i, t.f, t.d);

    t.f = 0.5;
    printf("%d %f %f\n", t.i, t.f, t.d);

    t.d = 0.016677;
    printf("%d %f %f\n", t.i, t.f, t.d);
  }

728x90
반응형

'Language > C' 카테고리의 다른 글

[C] 파일 처리 함수 - 2  (0) 2021.01.02
[C] 파일 처리 함수 - 1  (0) 2021.01.01
[C] 구조체와 공용체 -1  (0) 2020.12.27
[C] 배열과 포인터 - 3  (0) 2020.12.27
[C] 배열과 포인터 - 2  (0) 2020.12.27

구조체와 공용체 - 1

구조체와 필요성, 정의 방법과 구조체 변수, 구조체 배열과 구조체 포인터.

  • 학습 목표
    1. 구조체의 개념과 필요성 이해.
    2. 구조체의 정의와 구조체 변수 선언.
    3. 구조체 멤버 참조.
    4. 구조체 배열 사용.
    5. 구조체 포인터 사용.

주요 용어

  • 구조체 : 서로 다른 자료형을 갖는 자료들을 하나의 자료형으로 정으하여 사용하는 사용자 정의 자료형.
  • 구조체 멤버 : 구조체를 구성하는 변수.
  • 구조체 변수 : 정의된 구조체를 다루기 위한 변수.

구조체의 개념과 필요성

구조체(structure)

서로 다른 자료형을 갖는 자료의 모임을 하나의 자료형으로 정의하여 사용하는 자료형.
구조체 => 사용자 정의 자료형.

  • 다양한 형식의 자료를 간결한 형식으로 표현 가능.
  • 사용자가 새로운 형식을 정의하여 사용할 수 있음.

필요성

  char car1_maker[15];
  long int car1_km;
  long int car1_cost;

  char car2_maker[15];
  long int car2_km;
  ...

  long int car10_cost;
  struct vehicle {
    char maker[15];
    long int km;
    long int cost;
  }

  vehicle[10];

구조체의 정의와 변수 선언

구조체 정의

  • 형식
    •   struct 구조체_명 {
          멤버 _1;
          멤버 _2;
          ...
        }
  • ex
    •   struct score {
          int kor;
          int eng;
          ...
        }

구조체 변수의 선언

  • 형식
    •   struct 구조체_명 변수1, 변수2, 변수3;
  • EX
    •   struct score x, y[10], *z;

구조체 정의와 변수 선언 예 - 1

  • 실제 자료 형태

    • 학번 : 201XXXXXXX
    • 이름 : name
    • 국어 : 80
    • 영어 : 89
    • 수학 : 79
    • 국사 : 80
  • 구조체 정의

    •   struct score {  //  구조체 정의
          char no[10];  //  구조체 멤버
          char name[8];
          int kor;
          int ent;
          ... 
        }
      
        struct score x, y;  //  구조체 변수 x, y 선언

구조체 정의와 변수 선언 예 - 2

  struct score {
    char no[10];
    int ent;
    ... 
  } x, y;  //  구조체 변수 x, y 선언

구조체 정의와 변수 선언 예 - 3

  typedef struct score {
    char no[10];
    int ent;
    ... 
  } jumsu;  //  struct score를 jumsu라는 새로운 자료형으로 정의.
  jumsu x, y; //  새로운 자료형 jumsu의 변수 x, y 선언.

구조체 변수의 초기화 및 참조

초기화

  struct person {
    char name[8];
    int age;
    char gender;
  };

  struct person x = {"asdf", 20, 'M'};
  struct person {
    char name[8];
    int age;
    char gender;
  } x = {"asdf", 20, 'M'};

참조

. 연산자 사용

  • 형식
    • 구조체변수명.멤버명
    • x.name
    • x.age
  #include <stdio.h>
  #include <string.h>

  struct person //  person형 구조체 선언
  {
    char name[8];
    int age;
    char gender;
  };

  void main()
  {
    //  구조체변수 x 선언, 초기화
    struct person x = {"asdf", 20, 'M'};

    //  구조체변수 y선언
    struct person y;
    //  구조체멤버에 값 대입(문자열 처리할 경우 문자열 복사함수 strcp() 사용).
    strcpy(y.name, "qwer");
    y.age = 20;
    y.gender = 'F';

    printf("x -> %s, %d, %c\n", x.name, x.age, x.gender);
    //  x -> asdf, 20, M
    printf("y -> %s, %d, %c\n", y.name, y.age, y.gender);
    //  y -> qwer, 20, F
  }

구조체의 기억공간 구조

 

구조체의 기억공간 구조

실제로 메모리가 할당될 때는 구조체 멤버 중 가장 큰 자료형의 크기로 할당 됨.
person.gender가 char 형이지만, 멤버 중 가장 큰 int 형의 크기인 4byte가 할당 됨.

  #include <stdio.h>
  #include <string.h>

  struct person //  person형 구조체 선언
  {
    char name[8];
    int age;
    char gender;
  };

  void main()
  {
    struct person x = {"asdf", 20, 'M'};

    printf("sizeof(person.name)   : %d byte\n", sizeof(x.name));   //  8
    printf("sizeof(person.age)    : %d byte\n", sizeof(x.age));    //  1
    printf("sizeof(person.gender) : %d byte\n", sizeof(x.gender)); //  1
    printf("sizeof(person)        : %d byte\n", sizeof(x));        //  16
  }

구조체 배열

동일한 구조를 갖는 구조체 변수가 여러 개 사용 될 때,
그 구조체 변수들을 대표하는 배열명을 설정하여 일반 배열과 같이 사용.

  • EX : 3명의 개인 신상정보를 저장하기 위한 구조체 배열 선언.
  struct person {
    char name[8];
    int age;
    char gneder;
  } x[3];

  struct person y[3];

구조체 배열의 기억공간 표현

- char name[8] int age char gender
x[0] x[0].name x[0].age x[0].gender
x[1] x[1].name x[1].age x[1].gender
x[2] x[2].name x[2].age x[2].gender

구조체 배열의 초기화

  struct person x[3] = {
    {"qwer", 20, 'M'}
    , {"asdf", 21, 'F'}
    , {"zxcv", 22, 'M'}
  }

구조체 배열의 참조

  //  구조체배열 2번째 요소 name에 'asdf' 저장.
  strcp(x[1].name, "asdf");
  //  구조체배열 3번째 요소 gneder에 'F' 저장.
  x[2].gender = 'F';
  //  구조체배열 3번째 요소 age 값을 변수 K에 저장.
  K = x[2].age;

구조체 배열의 사용 예

  #include <stdio.h>
  #include <string.h>

  struct person //  person형 구조체 선언
  {
    char name[8];
    int age;
    char gender;
  };

  void main()
  {
    //  구조체 배열 초기화.
    struct person x[3] =
        {
            {"qwer", 20, 'M'},
            {"asdf", 21, 'F'},
            {"zxcv", 22, 'M'}};

    int i, sum = 0;

    for (i = 0; i < 3; i++)
    {
      //  구조체 배열의 멤버 참조.
      printf("name : %s, age : %d, gender : %c\n", x[i].name, x[i].age, x[i].gender);
      sum = sum + x[i].age;
    }

    printf("SUM OF AGE : %d\n", sum);
  }

구조체 포인터

포인터를 사용하여 구조체를 다룰 수 있게 함.

  • 구조체를 보다 쉽게 다를 수 있음.
  • 구조체 변수 선언시 * 를 붙여 포인터로 선언.
  • 구조체 포인터는 포인터와 동일하게 주소값을 갖게 되며, 자료가 있는 곳을 가르킴.

구조체 포인터 선언

  • 형식 : struct 구조체_명 *포인터변수_명;
  • 사용 예 : struct person *pt;
  //  구조체 변수 man 선언
  struct person man;
  //  구조체 포인터 변수 pt 선언
  struct person *pt;
  //  구조체 포인터 변수의 초기화
  pt = &man;

구조체 포인터의 기억공간 표현

구조체 포인터의 기억공간 표현

 

구조체 포인터의 멤버 참조

  • . 도트 연산자 사용
    • (*pt).name
  • 포인터 연산자 -> 사용
    • pt -> name

구조체 포인터의 사용 예

  #include <stdio.h>

  struct student
  {
    char name[10];
    int kor;
    int math;
  };

  void main()
  {
    struct student classmate[4] =
        {
            {"A", 90, 80},
            {"B", 80, 90},
            {"C", 85, 85},
            {"D", 70, 100}};

    //  구조체 포인터 선언
    struct student *p;
    //  구조체 포인터 변수에 구조체의 시작주소 대입
    p = classmate;

    printf("%s %d %d\n", p->name, p->kor, p->math);
    p += 3;
    printf("%s %d %d\n", p->name, p->kor, p->math);
    p--;
    printf("%s %d %d\n", p->name, p->kor, p->math);
  }

실행 과정 (기억공간 표현)

 

 


728x90
반응형

'Language > C' 카테고리의 다른 글

[C] 파일 처리 함수 - 1  (0) 2021.01.01
[C] 구조체와 공용체 - 2  (0) 2021.01.01
[C] 배열과 포인터 - 3  (0) 2020.12.27
[C] 배열과 포인터 - 2  (0) 2020.12.27
[C] 배열과 포인터 - 1  (0) 2020.12.25

배열과 포인터 - 3

char형 포인터, 포인터와 배열의 상관관계, 포인터 배열, 이중 포인터.

  • 학습 목표
    1. char형 포인터를 이용하여 문자열 다루기.
    2. 포인터를 배열 형식으로, 배열을 포인터 형식으로 참조하기.
    3. 포인터 배열 사용.
    4. 이중 포인터에 대한 이해.

주요 용어

  • char형 포인터 : 문자열 처리에 효과적인 포인터.
  • 포인터 배열 : 포인터가 여러 개 사용될 때 포인터를 배열형식으로 사용.
  • 이중 포인터 : 자료가 있는 곳을 이중으로 가리키는 포인터.

char형 포인터

  • 포인터는 문자열 처리에 효과적임.
  • 문자열 처리에 char형 포인터 사용하면 효율성이 극대화 됨.
    • char *cp = "COMPUTER";

char 포인터의 기억공간 표현과 예

 

char 포인터의 기억공간 표현과 예

 

  #include <stdio.h>

  int main()
  {
    //  char형 포인터 변수 cp의 값은 COMPUTER가 수록된 시작주소.
    char *cp = "COMPUTER";
    int i = 0;

    do
    {
      printf("*(cp + %d) : %c\n", i, *(cp + i));
    } while (*(cp + i++) != 0); //  *(cp + i)를 구한 후 1 증가.

    return 0;
  }
  /**
   * *(cp + 0) : C
   * *(cp + 1) : O
   * *(cp + 2) : M
   * *(cp + 3) : P
   * *(cp + 4) : U
   * *(cp + 5) : T
   * *(cp + 6) : E
   * *(cp + 7) : R
   * *(cp + 8) : 
  */

포인터와 배열의 관계

포인터를 이용한 1차원 배열의 참조와 예.

 

포인터를 이용한 1차원 배열의 참조와 예.

  #include <stdio.h>

  void main()
  {
    static int a[] = {10, 20, 30, 40, 50};
    int *pt, b, c, d;

    // 배열명을 사용하여 배열의 시작주소를 할당 -> a[0]
    pt = a;

    // a[0] + a[3] = 10 + 40 = 50
    b = *pt + *(pt + 3);

    //  포인터를 1 이동 a[1]
    pt++;

    //  a[1] + a[4] = 20 + 50 = 70
    c = *pt + *(pt + 3);

    //  a[1] + 3 = 23
    d = *pt + 3;

    printf("b = %d, c = %d, d = %d\n", b, c, d);
    //  b = 50, c = 70, d = 23
  }

포인터를 이용한 2차원 배열의 참조와 예.

 

포인터를 이용한 2차원 배열의 참조와 예

#include <stdio.h>
void main()
{
  static a[3][3] = {
      {1, 2, 3}
    , {4, 5, 6}
    , {7, 8, -9}
  };
  int *pt;

  //  pt = a 또는 pa = &a[0][0]과 동일
  pt = a[0];

  while (*pt != -9)
  {
    printf("%d ", *pt);
    pt++;
  }
}

포인터와 배열은 상호 호환적.

  int A[] = {1, 2, 3, 4, 5};
  int *p, i;
  // -->>
  A + i == &A[i];
  A[i] == *(A + i);
  *( p + i ) == p[i];
  #include <stdio.h>

  void main()
  {
    char A[] = "ARRAY";
    char *p = "POINTER";
    int i;

    for (i = 0; i < 5; i++)
    {
      //  배열을 포인터 형식으로 참조.
      printf("*(A + %d) : %c\n", i, *(A + i));
    }

    for (i = 0; i < 7; i++)
    {
      //  포인터를 배열 형식으로 참조.
      printf("p[%d] : %c\n", i, p[i]);
    }
  }

포인터와 배열의 관계

  • 포인터와 배열의 값 변경
    • 배열 : A[i]에서 A++, A--로 값 변경 불가.
    • 포인터 : *p에서 p++, p--로 값 변경 가능.
  • 배열과 포인터의 기억공간 확보
    • 배열
      • 기억공간 중 자료여역을 고정적으로 확보.
    • 포인터
      • 기억공간 중 자료영역을 유동적으로 확보.
        • 필요할 때만 자료용 기억 공간을 확보.
        • 자료의 개수가 가변적인 경우 효과적.
    • 포인터가 배열보다 활용의 폭이 넓다.

포인터 배열

포인터 배열 -> 포인터의 집합.

  • 포인터가 여러 개 사용될 때 포인터 배열로 선언.
  • 주로 문자열 배열 처리에 사용.
    • char *str1, *str2, *str3; -> char *strs[3];

포인터 배열 선언과 기억공간 표현

 

포인터 배열 선언과 기억공간 표현

포인터 배열 사용 예

  #include <stdio.h>

void main()
{

  int a[] = {1, 2, 3, 4};
  int b[] = {5, 6, 7, 8};

  // 포인터 배열의 선언.
  int *PA[2];
  //  배열 a[]의 시작주소를 포인터 배열요소에 전달.
  PA[0] = a;
  //  배열 b[]의 시작주소를 포인터 배열요소에 전달.
  PA[1] = b;

  printf("*(PA[0]) = %d\n", *(PA[0]));         //  1
  printf("*(PA[0] + 1) = %d\n", *(PA[0] + 1)); //  2

  printf("*PA[1] = %d\n", *PA[1]);           //  5
  printf("*PA[1] + 15 = %d\n", *PA[1] + 15); //  20
}

이중 포인터 (Pointer to pointer)

자료가 있는 곳을 이중으로 가리키는 포인터.
이중 포인터가 가리키는 주소에 데이터가 아닌 주소 값이 들어 있음.

이중 포인터의 선언

  • 형식 : int **p;
  • 의미 : 포인터 변수에 다시 포인터를 지정하는 것으로, 포인터에 대한 포인터.
    • P : 기억공간 주소.
    • *P : 주소 P에 수록되어 있는 값. 이 값이 주소로 사용 됨.
    • **P : 주소가 *P인 곳에 수록되어 있는 int형 데이터 값.
  #include <stdio.h>

  void main()
  {
    char a = 'A', *p, **pp;

    //  포인터 변수에 일반변수 a의 주소 할당.
    p = &a;

    //  이중 포인터변수에 포인터변수 p의 주소 할당.
    pp = &p;

    printf("**pp = %c", **pp);
  }

 

이중 포인터의 선언


728x90
반응형

'Language > C' 카테고리의 다른 글

[C] 구조체와 공용체 - 2  (0) 2021.01.01
[C] 구조체와 공용체 -1  (0) 2020.12.27
[C] 배열과 포인터 - 2  (0) 2020.12.27
[C] 배열과 포인터 - 1  (0) 2020.12.25
[C] 함수와 기억 클래스 - 2  (0) 2020.12.25

배열과 포인터 - 2

포인터의 개념, 포인터의 선언과 참조방법, 포인터의 기억공간의 표현, 포인터 연산.

  • 학습 목표
    1. 변수의 주소 이해.
    2. 표인터 개념 이해.
    3. 포인터 변수 선언 및 참조.
    4. 포인터 기억공간 표현의 이해.
    5. 포인터 연산의 이해.

주요 용어

  • 포인터 : 변수의 주소 값을 갖는 특별한 변수.
  • void형 포인터 : 프로그램 실행 시에 자료형이 경정되는 경우에 사용되는 포인터.
  • 포인터 연산 : 포인터 변수에 +, -, ++, -- 연산자를 사용하는 연산.

포인터(pointer)의 개념

pointer : 변수의 일종.

  • 변수 : 특정 데이터 값을 가지고 있음.
  • 포인터 : 특정 데이터가 저장된 기억장소의 주소(번지)값을 가지고 있음.

기억공간을 변수명으로 접근하지 않고 주소로 접근하기 위해 사용.

일반적인 변수의 기억공간 표현

  • 변수는 변수 선언에 의해 기억공간이 할당됨.
  • 할당된 기억공간에 변수에 대입된 데이터가 저장.
  • 할당된 기억공간은 주소(번지)가 부여되어 있음.

  • -> 변수가 주소를 의미 한다면, 주소를 이용하여 변수와 같은 동일한 작업이 가능하다.
    • -> 따라서 주소값(포인터 값)을 다룰 수 있는 변수가 필요.
    • -> 포인터 변수 : 변수의 주소 값을 갖는 특별한 변수.

변수 주소의 예

  #include <stdio.h>

  void main()
  {
    int days = 365;
    int month = 12;
    int Table[5] = {1, 2, 3, 4, 5};

    //  & : 주소를 의미한다.
    printf("addr of days : %x\n", &days);
    printf("addr of month : %x\n", &month);
    printf("addr of array : %x\n", Table); //  배열명은 기본적으로 주소를 나타냄.
    printf("addr of first element of array : %x\n", &Table[0]);
    printf("addr of second element of array : %x\n", &Table[1]);
  }

포인터변수의 선언

  • 형식 : 자료형 *포인터변수명;

  • 사용 예 : int *p;

  • 기능 : 변수 p는 포인터 변수로서 정수형의 자료를 갖는 변수의 주소를 갖는다.

  • int *p

    • p : 포인터 변수로서 정수 형 자료가 수록되어있는 주소를 갖고 있다.
    • *p : 해당 주소에 수록되어 있는 정수 형 자료를 갖고 있다.
  #include <stdio.h>

  void main()
  {
    int a, b;
    int *p; //  변수 p를 포인터 변수로 선언.

    a = 5000;

    p = &a; //  포인터 변수 p에 변수 a의 주소값 대입.

    b = *p; //  포인터 변수 p가 가리키는 주소의 내용을, 변수 b에 저장.

    printf("a : %d, b : %d, p : %x", a, b, p);
  }

 


포인터변수의 참조

포인터 변수의 참조 => &, * 연산자 사용.

  • 잘 못 된 예

 

  • 포인터변수의 올바른 참조 방법.

  • 포인터 변수의 참조 예

    •  

        #include <stdio.h>
      
        void main()
        {
          int *p, i = 3, j;
      
          p = &i; //  포인터 변수 p가 변수 i의 주소를 가리킴. 주소값 확보.
          j = *p; //  포인터 변수 p가 가리키는 번지의 내용을 변수 j에 대입.
          j++;    //  변수 j의 값을 1증가.
      
          printf("*p = %d\n", *p);
          printf(" p = %x\n", p);
          printf(" j = %d\n", j);
        }
        /**
         * p = &i;
         * 포인터 변수 p가 어느 공간을 가르킬 것인가.
         * 포인터 변수는 특정 기억공간을 가리키는 지시자이고,
         * 이 지시자가 어느 위치를 가르킬 것인지를 지정하는 것이 포인터 변수에서 제일 중요.
         */
  • 포인터 변수 참조의 기억공간 표현

void 형 포인터

  • 형식 : void *포인터명;
  • 의미 : 프로그램 실행시에 자료형이 결정되는 경우에 사용.
  • 저장하기 전에 명시적 형변환 필요.

void 형 포인터의 사용 예

  #include <stdio.h>

  void main()
  {
    int a = 100;
    char b = 'B';
    void *p = NULL; // void형 포인터를 선언 후 초기화

    p = (int *)&a;
    //  void형 포인터 p에 int형 변수 a의 주소를
    //  명시적 형변환을 이용하여 대입.
    printf("*p = %d\n", *(int *)p);

    p = (char *)&b;
    //  void형 포인터 p에 char형 변수 b의 주소를
    //  명시적 형변환을 이용하여 대입.
    printf("*p = %c\n", *(char *)p);
  }

일반 변수와 표인터 변수의 비교

    일반 변수   포인터 변수  
선언 int a; 정수형 변수 a 선언 int *a; 포인터변수 a를 정수형으로 선언
값 할당 a = 100; 변수 a에 100 할당 *a = 100; a 주소에 100 할당
주소 참조 &a 변수 a의 주소 a a 자체가 주소
주소 연산 연산 불가능   a--; 포인터를 1 감소

포인터 연산

포인터가 선언 되어있을 때 포인터와 포인터와 끼리의 계산이 가능하다.

포인터와 기억공간의 대응 관계

포인터 변수에 +, -, ++, -- 연산자를 사용하는 연산

  • int a[10], *p, *q;

포인터 연산의 예

  #include <stdio.h>

  void main()
  {
    int *p, a[] = {10, 20, 30, 40, 50};

    //  배열 첫 번째 요소의 주소값을 포인터변수 p에 저장.
    p = &a[0];

    printf("*p     == %d\n", *p); //  10
    //  포인터 p의 값 출력 후 주소를 1(4byte) 증가.
    printf("*p++   == %d\n", *p++); //  10
    //  포인터 p의 주소를 1(4byte) 증가 후 출력.
    printf("*++p   == %d\n", *++p); //  30

    //  포인터 p의 주소를 2(8byte) 증가
    p = p + 2;

    printf("*p     == %d\n", *p);   //  50
    printf("a[2]   == %d\n", a[2]); //  30
    //  포인터 p의 값에 2를 증가.
    printf("*p + 2 == %d\n", *p + 2); //  32
  }
  #include <stdio.h>

  void main()
  {
    int *p, *q;
    int a[] = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};

    p = &a[3];

    printf("*p       == %d\n", *p); //  40
    //  *(p + 3)과 *p + 3은 다르다.
    printf("*(p + 3) == %d\n", *(p + 3)); //  70

    q = p + 3;

    printf("*q       == %d\n", *q); //  70

    //  동일 배열을 가르키는 경우 두 포인터 간의 뺄샘.
    printf(" q - p   == %ld\n", q - p); //  3
    printf(" p - q   == %ld\n", p - q); //  -3

    //  두 포인터 간의 덧셈은 불가능.
    //printf(" p + q   == %d\n", p + q);
  }
728x90
반응형

'Language > C' 카테고리의 다른 글

[C] 구조체와 공용체 -1  (0) 2020.12.27
[C] 배열과 포인터 - 3  (0) 2020.12.27
[C] 배열과 포인터 - 1  (0) 2020.12.25
[C] 함수와 기억 클래스 - 2  (0) 2020.12.25
[C] 함수와 기억 클래스 - 1  (0) 2020.12.20

배열의 개념에 대해 알아보고, 배열의 정의와 선언 형태, 배열과 기억공간의 표현에 대해 알아본다.

  • 학습 목표

    1. 배열을 선언하고 초기화.
    2. 배열의 요소를 참조.
    3. 배열과 기억공간의 표현을 이해.
    4. char형 배열을 이해.

주요 용어

  • 배열 : 동일한 자료형으 ㅣ값들이 순서적으로 하나의 이름(배열명)에 모여있는 것으로, 같은 이름을 갖는 하나 이상의 변수 리스트.
  • 1차원 배열 : 배열의 첨자가 하나만 있는 배열.
  • 2차원 배열 : 배열의 첨자가 2개인 배열.
  • 3차원 배열 : 배열의 첨자가 3개인 배열.
  • char형 배열 : 문자열을 처리하기 위해 사용되는 배열.

배열의 개념

n개의 자료를 처리하기 위해, n개의 변수를 만들고 모든 변수 이름을 기억하고 자료를 처리하기는 복잡함. ->
일관성 있고 효율적인 새료운 변수릐 필요

  • 하나의 변수 이름에 순서에 의한 번호 부여.
  • 변수명[0], 변수명[2], ...
  • 효율적인 자료 처리 가능.

배열의 정의와 형태

  • 배열의 정의.
    • 동일한 자료형을 갖는 자료들의 리스트.
    • 배열의 각 요소는 하나의 변수로 취급.
    • 배열은 배열명첨자로 구분.
  • 배열 선언 형태.
    • 1차원 배열.
    • 2차원 배열.
    • 3차원 배열.

1차원 배열

  • 배열의 첨자가 하나만 있는 배열.
  • 첨자의 개수는 배열 전체의 구성요소의 개수를 의미.
  • 배열의 각 요소는 배열명과 첨자로 구분.
    • 첨자는 0 부터 시작.
  • 배열의 각 요소는 배열명과 첨자로 구분.
    • 자료형과 기억 클래스는 갖는다.

선언

  • 형식 : 자료형 배열명 [개수]
  • 사용 예 : int a [10]
  • 의미 : 1차원 배열로서, 배열명은 a, 크기는 10, 정수 값이 기억됨.

1차원 배열의 기억 공간 표현

1차원 배열의 기억 공간 표현

1차원 배열의 초기화

배열을 선언하면 기억공간을 초기화 해야 함.

  • 초기화 방법.

    1. 배열선언 후 초기값 할당.

      •  int arr[4];  // -> 반드시 배열의 크기를 지정해야 함.
         arr[0] = 10;
         arr[1] = 20;
         arr[2] = 30;
         arr[3] = 40;
    2. 배열선언과 동시에 초기값 할당.

      •  int arr[4] = {10, 20, 30, 40};      //  -> 배열의 각 요소에 초기 값 할당.
         int arr[] = {10, 20, 30, 40};       //  -> 배열의 크기 생량 가능.
         int arr[4] = {10, 20, 30,};         //  -> arr[3] = 0으로 초기화.
         int arr[4] = {10, , 30, 40};        //  -> 에러 발생.
         int arr[4] = {10, 20, 30, 40, 50};  //  -> 에러
    3. 외부로부터 자료를 입력받아 초기화.

      •  int x[10];
         for( i = 0; i < 10; i++ ) {
           scanf("%d", &x[i]);
         }
  • 1차원 배열의 초기화 후 기억공간의 표현
    int arr[5] = {10, 20, 30, 40, 50};

1차원 배열의 초기화 후 기억공간의 표현

 

  • EX 1

    • #include <stdio.h>
      
      int main()
      {
        //  배열 선언과 초기화
        int arr1[4] = {10, 20, 30, 40};
        int arr2[] = {10, 20, 30, 40};
        int arr3[4] = {10, 20};
        int arr4[4] = {0};
        int i;
      
        printf("\narr1 ->\n\t");
        for (i = 0; i <= 3; i++)
        {
          printf("[%d] : %d\t", i, arr1[i]);
        }
        printf("\narr2 ->\n\t");
      
        for (i = 0; i <= 3; i++)
        {
          printf("[%d] : %d\t", i, arr2[i]);
        }
        printf("\narr3 ->\n\t");
        for (i = 0; i <= 3; i++)
        {
          printf("[%d] : %d\t", i, arr3[i]);
        }
        printf("\narr4 ->\n\t");
        for (i = 0; i <= 3; i++)
        {
          printf("[%d] : %d\t", i, arr4[i]);
        }
        printf("\n");
      
        return 0;
      }
  • EX 2

    •   #include <stdio.h>
      
        int main()
        {
          //  1차원 배열 선언과 초기화
          static int x[] = {1, 2, 3, 4};
          static int y[] = {10, 20, 30, 40};
      
          int i, z[4];
      
          for (i = 0; i < 4; ++i)
            z[i] = x[i] + y[3 - i];
      
          printf("SUM OF OTHER SIDE OF EACH ARRAY\n");
      
          for (i = 0; i < 4; ++i)
            printf("%d + %d = %d\n", x[i], y[3 - i], z[i]);
      
          return 0;
        }

2차원 배열 선언

  • 형식 : 자료형 배열명[행의 수][열의 수]
  • 사용 예 : int a[3][4];
  • 의미 : 2차원 배열로, 배열 명은 a이고, 3행 4열로 됨 12개의 요소를 가진 정수형 배열.

2차원 배열의 선언과 초기화

  int arr[3][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
  int arr[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
  int arr[3][3] = {
      {1, 2, 3}
    , {4, 5, 6}
    , {7, 8, 9}
  };

2차원 배열의 기억공간 표현

 

2차원 배열의 기억공간 표현

 

2차원 배열의 사용 예

  #include <stdio.h>

  int main()
  {
    static int score[4][3] = {
        {90, 90, 90},
        {80, 80, 80},
        {70, 70, 70},
        {60, 60, 60}};
    int sum, i, j;

    printf("No\tA\tB\tC\tSUM\n");

    for (i = 0; i < 4; ++i)
    {
      sum = 0;
      printf("%3d", i + 1);

      for (j = 0; j < 3; j++)
      {
        printf("\t%3d", score[i][j]);
        sum += score[i][j];
      }
      printf("\t%3d\n", sum);
    }

    return 0;
  }

3차원 배열의 선언

  • 형식 : 자료형 배열명 [면의 수] [행의 수] [열의 수];
  • 사용 예 : int a[2][3][4];
  • 의미 : 3차원 배열로서, 배열 명은 a이고, 2면 3행 4열로 된,
    24개 요소를 가진 정수형 배열.

3차원 배열의 초기화와 기억공간 표현

 

3차원 배열의 초기화와 기억공간 표현


char형 배열

  • 형식 : char 배열명[문자열 길이 + 1]
  • 사용 예 : char str[12]
  • 의미 : 배열명 str, 12문자 길이를 가진 char 형 배열.

char형 배열선언과 초기화

  char name[] = "JEAHA OH"; // 문자열 단위로 초기화
  char addr[] = {'S', 'E', 'O', 'U', 'L', '\0'}; // 문자 단위로 초기화. '\0'을 삽입 해야 함.

char형 배열 사용 예

  #include <stdio.h>

  int main()
  {
    char name[] = "JEAHA OH";
    char addr1[6] = {'S', 'E', 'O', 'U', 'L', '\0'}; // 마지막 요소 \0 삽입
    char addr2[6] = {'S', 'E', 'O', 'U', 'L'};       //  마지막 요소 \0을 삽입하지 않을 경우 쓰레기 값이 붙을 수 있음.

    printf("\n name : %s", name);
    printf("\n addr1 : %s", addr1);
    printf("\n addr2 : %s", addr2);
    return 0;
  }
  #include <stdio.h>

  int main()
  {
    char string[50];
    int i = 0;

    printf("\t INSERT SOMETHING STRING >> ");
    scanf("%s", string);

    printf("RECEIVED STRING : %s\n", string);
    printf("PRINT AS CHARACTER : ");

    while (string[i] != '\0')
    {
      printf("%c", string[i]);
      i++;
    }
    printf("\n");
    return 0;
  }

함수와 배열

  • 배열을 함수의 매개변수로 사용할 경우
    • 함수 호출 시 배열명만 명시하여 호출.
    •   int score[2][5] = {{1, 2, 3, 4, 5}, {1, 1, 1, 1, 1}};
        score_sum( score, 2, 5);
  • 함수의 헤더에는
    • 1차원 배열의 경우 크기 생략 가능
    • 다차원 배열의 경우 가장 높은 차원의 크기 생략 가능.
  #include <stdio.h>

  void score_sum(int gr[][5], int, int);

  int main()
  {
    int score[2][5] = {
        {10, 20, 30, 40, 50},
        {10, 10, 10, 10, 10}};

    score_sum(score, 2, 5);

    return 0;
  }

  void score_sum(int gr[][5], int row, int column)
  {
    int sum[2] = {0};
    int i, j;

    for (i = 0; i < row; i++)
    {
      for (j = 0; j < column; j++)
      {
        sum[i] += gr[i][j];
        printf("SUM[%d] = %d\n", i, sum[i]);
      }
    }

    printf("\n");
  }

728x90
반응형

'Language > C' 카테고리의 다른 글

[C] 배열과 포인터 - 3  (0) 2020.12.27
[C] 배열과 포인터 - 2  (0) 2020.12.27
[C] 함수와 기억 클래스 - 2  (0) 2020.12.25
[C] 함수와 기억 클래스 - 1  (0) 2020.12.20
[C] 선택 제어문과 반복 제어문  (0) 2020.12.20

함수와 기억 클래스 - 2

함수의 호출방법, 호출 함수와 피 호출함수사이의 자료전달방법, 변수의 유효범위아 기억클래스의 개념.

  • 학습 목표

    1. 값에 의한 자료 전달 방법과 참조에 의한 자료전달방법의 차이 이해.
    2. 지역 변수와 전역변수의 이해.
    3. 기억클래스의 의해.

주요 용어

  • 기억 클래스 : 변수를 기억공간의 특정 영역에 할당하는 방법.
  • 지역 변수 : 특정 범위 내에서만 사용되는 변수.
  • 전역 변수 : 프로그램 전체에 걸쳐 사용될 수 있는 변수.
  • 자동 변수 : 함수 실행 시 만들어 지고 실행이 끝나면 기억공간이 제거되는 유형.
  • 정적 변수 : 프로그램이 끝날 때까지 기억영역이 유지되는 유형.
  • 외부 변수 : 함수외부에서 선언되어 프로그램이 끝날 때가지 기억영역이 유지되는 유형.
  • 레지스터 변수 : CPU내의 레지스터에 자료를 저장하고자 할 때 사용되는 유형.

매개변수 사이의 자료 전달

Call By Value - 값에 의한 자료 전달

  • 기본적인 자료전달 방법.

  • 실 매개변수와 형식 매개변수 사이에 값의 전달.

  • 호출한 함수의 실행이 끝난 다음 전달받은 값을 되돌려 받지 못함.

  • 구조

    •   func1(10, 20); // 함수호출(실 매개변수)
        ...
        int func(int x, int y) // 함수 정의 (형식 매개변수)
  • EX

    •   #include <stdio.h>
      
        void swap(int x, int y);
      
        int main()
        {
          int a = 3, b = 5;
      
          printf(":: Before Call a = %d, b = %d\n", a, b); //  ::  a = 3, b = 5
      
          swap(a, b);
      
          printf(":: After Call a = %d, b = %d\n", a, b);  //  :: a = 3, b = 5
          return 0;
        }
      
        void swap(int x, int y)
        {
          x ^= y;
          y ^= x;
          x ^= y;
          printf(">> Inside swap x = %d, y = %d\n", x, y); //  >> x = 5, y = 3
        }
  • 값에 의한 자료 전달 과정


Call By Reference - 참조에 의한 자료 전달

  • 호출함수와 피 호출함수의 매개변수 값을 서로 교환할 수 있는 자료전달 방법.

  • 값을 전달하는 것이 아니라 실 매개 변수의 값이 들어있는 주소 값이 전달됨.

  • 구조

    •   func1(&a, &b); // 함수호출 (실 매개변수)
        ...
        int func1( int * x, int * y) // 함수 정의 (형식 매개변수)

& : 주소 연산자.

호출 하는 곳에서는 &를 붙여서 주소를 전달하는 것을 명시적으로 표현.

* : 내용 연산자. (*가 붙은 변수를 포인터 변수라고 한다.)

호출 당하는 곳에서는 *를 붙여서 주소가 가르티는 내용을 사용함을 명시적으로 표현한다.

  • EX

    • 참조에 의한 자료 전달방법은 피호출 함수 내에서 값의 변화가 일어나면 실 매개변수의 값도 변화됨.

    •   #include <stdio.h>
      
        void swap(int *x, int *y);
      
        int main()
        {
          int a = 3, b = 5;
      
          printf(":: Before Call a = %d, b = %d\n", a, b); //  :: a = 3, b = 5
      
          swap(&a, &b);
      
          printf(":: After Call a = %d, b = %d\n", a, b); //  :: a = 5, b = 3
          return 0;
        }
      
        void swap(int *x, int *y)
        {
          *x ^= *y;
          *y ^= *x;
          *x ^= *y;
          printf(">> 4. Inside swap x = %d, y = %d\n", *x, *y); //  >> a = 5, b = 3
        }
  • 참조에 의한 자료 전달 과정


기억 클래스 (Storage class)

  • 변수를 기억공간의 특정영역에 할당하는 방법.
  • 즉, 각 변수의 유효범위와 존속기간을 설정.
    • 변수의 사용 위치에 따라.
      • 지역 변수.
      • 전역 변수.
    • 변수의 존속기간에 따라
      • 자동 변수.
      • 정적 변수.
      • 외부 변수.
      • 레지스터 변수.

지역변수와 전역변수

지역 변수 (local variable)

  • 특정 범위 내에서만 통용되는 변수.

  • 선언된 블록이나 함수 내에서만 사용 가능.

  • 함수에서 사용되는 매개변수에도 해당.

  • 지역변수 사용 예

    •   #include <stdio.h>
      
        void func();
      
        int main()
        {
          //  main()) 내부에 선언되어 main()에서만 사용가능한 지역변수
          int i = 10;
      
          printf("\n main i : %d", i);
      
          func();
      
          printf("\n main i : %d\n", i);
      
          return 0;
        }
      
        void func()
        {
          //  main()의 i와는 별개인 지역변수.
          int i;
      
          i = 20;
          printf("\n func i : %d", i);
        }
    •   #include <stdio.h>
      
        int main()
        {
          // BLOCK A
          int x = 2, y = 4;
      
          printf("A >> x : %d, y : %d\n", x, y);
      
          {
            //  BLOCK B
            int x;
            x = 5;
            y++;
            printf("B >> x : %d, y :%d\n", x, y);
          }
          printf("A >> x : %d, y :%d\n", x, y);
        }

전역 변수 (global variable)

  • 함수 밖이나 외부 파일에서 선언되어 프로그램 전체에 걸쳐 사용될 수 있는 변수
  int x, y; //  변수 x, y는 **프로그램 전체에서 사용가능한 전역변수**(함수 외부에서 선언됨)

  long func1 (int m, int n) {
    x++, y--;
    m++, n--;
    //  변수 m, n은 func1 내에서만 사용 가능한 **지역변수**.
  }

  void func2 () {
    int m, n;
    //  func2()의 **지역변수**.
  }

  void main(){
    int m, n;
    // main()에서만 사용 가능한 **지역변수**.
    long x;

    x = func1( 10, 20 );
    func2()
  }
  • EX

    •   #include <stdio.h>
      
        void func();
        int x;
        //  **전역변수**, 가급적 프로그램의 선두에 위치하는 것이 좋음.
        //  전역변수는 초기화 안 하면 **0으로 자동 초기화**.
      
        int main()
        {
      
          printf(" 1 ) x : %d\n", x);
      
          func();
      
          printf(" 2 ) x : %d\n", x);
      
          return 0;
        }
      
        void func()
        {
          //  전역 변수이기 때문에 어디서나 사용 가능.
          x++;
        }

전역 변수와 지역변수의 비교

  • 동일 범위 내에서는 지역변수가 우선.
  • 전역변수의 선언은 프로그램 선두에 위치.
  • 가급적 지역변수를 사용하는 것이 효율적.
    • 함수의 독립성 향상.
    • 디버깅 효율 향상.
    • 기억공간 절약.

변수의 기억 클래스 종류

  • 변수의 초기화, 존속기간, 유효범위에 따라 구별.
    • 자동 (auto)
    • 정적 (static)
    • 외부 (extern)
    • 레지스터 (register)

기억 클래스를 이용한 변수 선언

  • 형식 : 기억클래스 자료형 변수명;
  • 기능 :
    • 기존의 변수 선언문에 기억클래스만 기입.
    • 선언된 변수에 저장도니 자료는 해당 기억영역에 놓이게 됨.
  • 사용 예
    • auto int a;
    • static int b;
    • extern int c;
    • register int c;

자동변수

  • 함수 실행시 만들어지고, 실행이 끝나면 기억공간이 제거됨.
  • 예약어 auto를 사용 (생략 가능)
  • 통용 범위는 변수가 선언된 블록이나 함수 내로 한정.
  • 지역변수에 해당.
  • 초기화 필요.
  #include <stdio.h>

  int main()
  {
    int i = 1;
    auto int j = 2;
    { //  BLOCK A
      int i = 3;
      { //  BLOCK B
        int i = 4;

        printf("i in BLOCK B : %d\n", i);
        printf("j in BLOCK B : %d\n", j);
      }
      printf("i in BLOCK A : %d\n", i);
    }
    printf("i in BLOCK MAIN() : %d\n", i);

    return 0;
  }

정적변수

  • 기억 영역이 프로그램 끝날 때까지 유지.
  • 예약어 static 사용.
  • 전역 변수에 해당.
  • 변수의 값은 프로그램 실행 중 계속 유지.
  • 초기화가 없으면 0 으로 초기화 됨.
  #include <stdio.h>

  int main()
  {
    //  자동 변수 선언
    int a = 10;
    //  정적 변수 선언
    static int b = 20;

    {
      int a = 5;
      printf("a : %d b : %d\n", a, b);
      // a는 자동 변수이므로 블럭 안에서만 효력이 발생함.
    }
    printf("a : %d b : %d\n", a, b);

    return 0;
  }
  #include <stdio.h>

  void test();

  int main()
  {
    int i = 0;

    while (i < 3)
    {
      test();
      i++;
    }

    return 0;
  }

  void test()
  {
    auto int a = 0;
    static int s = 0;

    printf("auto : %d, statc : %d\n", a, s);

    ++a, ++s;
  }
  /**
   * auto : 0, statc : 0
   * auto : 0, statc : 1
   * auto : 0, statc : 2
   * 자동변수는 호출 될 때 마다 값이 초기화 되지만,
   * 함수 내에서 사용된
   * **정적 변수는 함수를 빠져 나가더라고 그 값을 유지**
   * (한번만 초기화 됨)
   */

외부 변수

  • 함수의 외부에서 선언.
  • extern 예약어 사용.
  • 전역 변수에 해당.
  • 초기화가 없으면 0으로 초기화 됨.
  • 다른 파일에서 외부변수로 선언된 변수의 값을 참조할 수 있음.
  #include <stdio.h>

  int i = 10, j = 20;

  void main()
  {
    //  외부 변수 선언
    //  (**생략 가능**, 변수 i가 선언되면, 선언된 위치 이하부터 그 갑ㅆ이 유효하기 때문.)
    extern int i;
    //  외부 변수 선언
    //  (**생략 불가**, 변수 k가 범위 바깥에 있으므로 )
    extern int k;

    //  변수 j = 20, j = 100이 동시 선언시, **지역변수(자동변수)가 우선**
    int j = 100;

    printf("i : %d, j : %d, k : %d\n", i, j, k);
    //  i : 10, j : 100, k : 50
  }

  int k = 50;
  #include <stdio.h>
  #pragma warning(disable : 4996)

  //  extern_ex() 함수 원형 선언.
  void extern_ex();
  //  전역변수 s 선언.
  char s[100];

  int main()
  {
    printf("INSERT STRINGS : ");
    scanf("%s", s);

    printf("String (%s) WILL STORE GLOBAL VARIABLE S.\n", s);
    extern_ex(); // extern_ex() 호출

    return 0;
  }
  #include <stdio.h>

  extern char s[]; // 변수 s를 외부 변수로 선언

  void extern_ex()
  {
    //  외부 변수 s 출력.
    printf("EXTERNAL VARIABLE S IS \n%s\n", s);
  }

레지스터 변수

  • CPU 내의 레지스터에 자료를 저장하고자 할 때.
  • 예약어 register를 사용.
  • 자동 변수와 동일한 속성.
  • 프로그램의 실행속도 증가를 목적으로 사용.
    (주로 반복문에서 카운터 변수로 사용)
728x90
반응형

'Language > C' 카테고리의 다른 글

[C] 배열과 포인터 - 2  (0) 2020.12.27
[C] 배열과 포인터 - 1  (0) 2020.12.25
[C] 함수와 기억 클래스 - 1  (0) 2020.12.20
[C] 선택 제어문과 반복 제어문  (0) 2020.12.20
[C] 입출력 함수와 연산자 - 2  (0) 2020.12.20

함수와 기억 클래스 - 1

C 언어에서 함수의 개념, 표준함수와 사용자 정의 함수, 함수의 선언, 정의, 호출 방법.

  • 학습 목표

    1. 함수의 개념과 중요성 이해.
    2. 표준함수와 사용자 정의함수 이해.
    3. 함수의 선언, 정의, 호출 방법 이해.
    4. 표준함수에 대한 헤더파일 사용.

프로그램 언어의 제어 구조

  • 함수 : 특정한 작업(기능)을 수행하도록 설계된 독립적인 프로그램.
  • 표준 함수 : C 언어에서 자체적으로 제공하는 함수.
  • 사용자 정의함수 : 사용자가 정의하여 사용하는 함수.
  • 함수 원형 : 함수를 프로그램에서 사용하기 위한 함수의 양식.
  • 함수 호출 : 사용할 함수를 부르는 것.
  • 매개변수 : 호출하는 함수와 호출 당하는 함수에 쓰이는 변수.

함수의 개념

특정한 작업(기능)을 수행하도록 설계된 독립적인 프로그램.
정해진 순서에 따라 실행 됨으로 프로그램의 기능을 수행 함.

C 프로그램은 함수들로 구성

  • 전체의 실행 내용을 몇 개의 모듈(module)로 분류.
  • 각각의 모듈에 해당하는 내용을 함수로 작성.
  • 실행 순서에 따라 그 함수들을 차례로 호출하여 실행.

함수의 특성

  • 함수들은 서로를 자유롭게 호출 가능.
  • 모든 함수는 서로 독립적.

함수의 장점

  • 프로그램의 수정이 쉽다.
  • 함수의 재사용으로 코드 중복을 최소화 함.
  • 프로그램 기능을 한 눈에 파악할 수 있게 함으로 유지보수가 쉬움.

단위 프로그램을 하나의 함수에 기술 한 경우

  void main() {
    // 성적 입력 코드
    ...
    // 성적 수정 코드
    ...
    // 성적 처리 코드
    ...
    // 성적 출력 코드
    ...
  }
  • 함수의 길이가 커짐.
  • 프로그램 가독성이 낮음.
  • 수정의 어려움이 있음.
  • 일부분만 재호출 불가능.

표준 함수

C 언어에서의 함수

  • 표준함수 : C 언어 자체에서 제공하는 함수.
  • 사용자 정의함수 : 사용자가 정의하여 사용하는 함수.

표준 함수

  • 표준함수의 원형은 헤더파일(*.h)에 정의.
  • 표준함수의 실체는 라이브러리 파일에 수록.
  • 표준함수를 사용하려면 원형이 선언되어 있는 헤더파일을 #include 해줘야 함.

표준 함수의 원형 예

  • prntf(), scanf() 의 원형.
    •   int printf(const char * format, ...);
        int scanf(const char * format, ...);
    • stdio.h(standard input output의 약자)헤더파일에 정의 되어 있음.
    • 표준 함수를 사용하려면 #include <stdio.h>를 꼭 해야 함.
  • sin(), cos() 의 원형.
    •   double sin(double x);
        double cos(double x);
    • math.h 헤더파일에 정의되어 있음.
    • 표준함수를 사용하려면 #include <math.h>

C 언어 표준 함수의 대표적인 예

헤더 파일 선언된 함수 EX
stdio.h 입출력함수 printf(), scanf(), getchar(), putchar(), ...
stdio.h 파일 관련 함수 fopen(), fclose(), fprintf(), ...
conio.h 콘솔 입출력 함수 putch(), cputs(), cprintf()(), getch(), chetche(), cscanf(), ...
string.h 문자열 처리 함수 strcat(), strcmp(), strcpy(), strlen(), strncat(), strncpy(), ...
math.h 수학 함수 sqrt(), sin(), cos(), tan(), log(), exp(), pow(), abs(), asin(), acos(), atan(), cosh(), ...
ctype.h 문자 형태 판별 함수 isalpha(), isdigit(), islower(), ...
ctype.h 문자 변환 함수 tolower(), toupper()
stdlib.h 수치변환 함수 atoi(), itoa()
stdlib.h 난수 관련 함수 rand(), srand()
stdlib.h 정렬/검색 함수 qsort(), lfind()

표준함수 사용의 예

  •   #include <stdio.h> //  입출력 함수를 처리하기 위한 헤더파일 (standard input output)
      #include <math.h>  //  수학 함수를 처리하기 위한 헤더파일
      #include <stdlib.h>
    
      int main()
      {
        int a, b, c;
        int i = -5, j = 2;
        double x = 12.34;
    
        printf("abs( -5 ) = %d\n", abs(i)); //  x의 절댓값.
    
        a = ceil(x);
        printf("ceil( 12, 34 ) = %d\n", a); //  x 이상의 최소 정숫값.
    
        printf("cos( 10 ) = %f\n", cos(10));
    
        printf("exp( 2 ) = %.f\n", exp(j)); //  x의 지숫값
    
        b = floor(x);
        printf("floor( 12.34 ) = %d\n", b); //  x 미민의
    
        printf("sqrt( 2 ) = %5f\n", sqrt(j));
    
        c = pow(4, j);
        printf("pow( 4, 2) = %d\n", c); //  pow(x, y) : x의 y제곱 값.
    
        return 0;
      }
  •     #include <stdio.h>
        #include <string.h> //  문자열 처리 함수를 위한 헤더파일
        #include <ctype.h>  //  문자형태 판별 함수(isalphat, isdigit)을 위한 헤더
    
        int main()
        {
          int i, alp = 0, no = 0, et = 0;
          char s[20];
    
          printf("\n STRING : ");
          scanf("%s", s);
    
          for (i = 0; i < strlen(s); i++)
          {
            if (isalpha(s[i]))
              alp++;
            else if (isdigit(s[i]))
              no++;
            else
              et++;
          }
    
          printf("alphabe = %d\n", alp);
          printf("number = %d\n", no);
          printf("etc = %d\n", et);
          printf("totoal = %d\n", strlen(s));
    
          return 0;
        }

사용자 정의 함수

사용자가 단위 프로그램을 함수로 정의하여 사용.

  • C 프로그램에서의 함수

    • main()함수 안에 표준 함수를 사용하는 형태
    • 동일 블럭 내의 프로그램 길이가 길어지면, 전체 프로그램은 복잡해 지고 이해하기가 어려워짐.
    • 전체 프로그램을 짧은 단위 프로그램으로 나누어 정의함으로 프로그램의 작성과 이해를 쉽게 할 필요가 있음.
  • 사용자 정의 함수의 예

    •   #include <stdio.h>
      
        int sum(int a, int b);
      
        int main()
        {
      
          int x, y, c;
      
          printf("\nx : ");
          scanf("%d", &x);
      
          printf("y : ");
          scanf("%d", &y);
      
          c = sum(x, y);
      
          printf("\nSUM : %d\n", c);
      
          return 0;
        }
      
        int sum(int a, int b) //  사용자 정의함수
        {
          return a + b;
        }

함수 정의의 구조

  •   반환_자료형 함수명( 자료형 매개변수1, 자료형 매개변수2, ...)  // 함수 헤더
      { // 함수 시작
        // 함수 몸체
      } // 함수 끝
  •   int sum(int a, int b)
      {
        return a + b;
      }

함수 헤더.

  • 반환 자료형.
    • 함수의 결과 값을 호출한 함수에 되돌려 줄 때의 자료형.
    • 사용될 수 있는 자료형은 C 언어에서 사용 가능한 모든 자료형.
    • 생략 가능하며, 생략할 경우 자료형은 int로 간주.
    • 반환 값이 없는 함수인 경우 void 형으로 선언(생략시 int로 처리).
  • 함수명
    • 변수명을 정하는 규칙과 동일한 방식으로 함수명을 정함.
    • 의미 있는 함수명을 정하는 것이 함수를 이해하는 데 도움을 줌.
  • 자료형과 매개변수
    • 자료형은 매개변수의 자료형을 나타냄.
    • 매개변수는 호출 함수와 피호출 함수 사이에 자료를 주고받기 위헤 사용.
    • 매개변수는 해당 함수 내에서 변수처럼 사용.
    • 매개변수가 여러 개일 경우에는 콤마(,)로 구분.
    • 매개변수가 없으면 void 형으로 사용.

함수 몸체

  • 함수가 하는 일을 정의하는 부분.
  • 중괄호 {}를 이용하여 함수의 시작과 끝을 나타냄.
  • C언어의 기본 구조와 동일.

함수의 사용

  • 함수를 사용하기 위해서는 함수의 원형 선언, 함수의 호출, 함수의 정의로 구성.

함수의 원형 선언

  • 함수는 변수와 같이 사용되기 전에 미리 선언.

  • 함수의 원형 선언은 일반적으로 main() 이전에 함.

    • 컴파일 시, main()을 먼저 컴파일 하기 때문에, main()에서 사용할 함수를 미리 선언해 줘야 함.
  • 원형선언은 함수정의 부분의 헤더부분에 세미콜론(;)만 추가 하면 됨.

    • 함수 원형선언은 함수와 관련된 3가지 성질을 선언.
      • 함수의 반환형.
      • 배개변수의 개수.
      • 배개변수의 자료형.
  • 피호출 함수가 main() 뒤에 선언된 경우 함수의 원형선언이 필요.

    •   #include <stdio.h>
      
        int sum(int a, int b);
      
        int main()
        {
          printf("sum = %d\n", sum(10, 20));
      
          return 0;
        }
      
        int sum(int a, int b)
        {
          return (a + b);
        }
  • 피 호출 함수가 main() 앞에 선언된 경우 원형선언 필요 X.

    •   #include <stdio.h>
      
        int sum(int a, int b)
        {
          return (a + b);
        }
      
        int main()
        {
          printf("sum = %d\n", sum(10, 20));
      
          return 0;
        }

함수의 호출

  • 함수는 일종의 부 프로그램.
  • 함수의 호출이 있어야 함.
  • 함수 호출의 방법.
    • 함수명과 매개변수의 열거.
  • 함수 호출과 프로그램 실행순서.
    • main() 시작.
    • ()를 만나면 함수의 호출이 발생.
    • 해당 함수 시작.
    • 해당 함수 수행 결과 반환.
    • main()의 남은 부분 수행

매개변수

  • 실 매개변수
    • 함수를 호출하는 함수(호출함수)에 쓰이는 매개변수.
  • 형식 매개변수
    • 호출 당하는 함수(피 호출함수)에 쓰이는 매개변수.
  • 실 매개변수와 형식 매개변수 사이에는 자료형과 변수의 개수가 일치해야 함.
  • 자료형이 일치하지 않을 경우 형 변환 발생.
  • 변수의 개수가 일치하지 않을 경우 컴파일 에러 발생.
    •   void main() {
          fnc1( a, b, c ); // 호출함수로서 a, b, c는 실 매개변수
        }
        void fnc1(int x, float y, double z) {
          // 피 호출 함수로서 x, y, z는 형식매개변수
        }

결과값 반환 return

  • 기능 :

    • 함수를 끝내고 제어와 함수 수행 결과를 호출 함수로 넘김.
  • 형식 :

    • return (수식);
    • return 수식;
  • 사용 예

    •   return 0; -> 상수 0 반환. (정상적인 종료 의미.)
        return 1; -> 상수 1 반환.
        return x; -> x 값 반환.
        return (x + y * z); -> 수식의 결과 값 반환.
        return ( sum( 10, 20 ) ); -> 다른 함수 호출.
  •   #include <stdio.h>
    
      int max(int x, int y);
      int min(int x, int y);
    
      int main()
      {
    
        int i = 10, j = 20;
    
        printf("max( %d, %d ) => %d\n", i, j, max(i, j));
        printf("min( %d, %d ) => %d\n", i, j, min(i, j));
    
        return 0;
      }
    
      int max(int x, int y)
      {
        return (x > y ? x : y);
      }
    
      int min(int x, int y)
      {
        if (x > y)
          return y;
        else
          return x;
      }

함수의 여러 가지 사용 예

  #include <stdio.h>

  //  함수 원형 선언.
  int sum(int, int);
  void test();

  //  main.
  int main()
  {
    int s;

    //  단순 호출.
    test();
    sum(10, 20);

    // 함수 결과를 변수에 반환.
    s = sum(30, 40);

    printf("sum from 30 to 40 = %d\n", s);
    // 호출 결과를 직접 사용.
    printf("sum from 100 to 200 = %d\n", sum(100, 200));

    return 0;
  }

  void test()
  {
    printf("FUNCTION EXAMPLE\n");
  }

  int sum(int a, int b)
  {
    int i, s = 0;
    for (i = a; i <= b; i++)
      s = s + i;

    return s;
  }
728x90
반응형

'Language > C' 카테고리의 다른 글

[C] 배열과 포인터 - 1  (0) 2020.12.25
[C] 함수와 기억 클래스 - 2  (0) 2020.12.25
[C] 선택 제어문과 반복 제어문  (0) 2020.12.20
[C] 입출력 함수와 연산자 - 2  (0) 2020.12.20
[C] 입출력 함수와 연산자 - 1  (0) 2020.12.15

+ Recent posts