구조체와 공용체 - 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

+ Recent posts