1절  구조체

1.     구조체

n  사용자 정의 자료형!

n  다양한 자료형의 여러 값을 하나의 단위로 묶어 편리하게 관리하고 사용

n  여러 가지 다른 관련된 데이터들을 하나로 묶어 정의


 

2.     구조체의 개념

n  자료형이 다른 값들을 묶어서 관리할 수 있는 사용자 정의 자료형

n  대입문에서 편리 : 구조체 변수 간의 대입으로 한 개의 대입문으로 대입 끝(원소 하나하나 접근X)


3.     구조체의 정의와 변수의 선언

n  구조체형 변수에 선언하려면 사용하기 전

템플릿(미리 사용할 구조체의 형태)을 먼저 정의 구조체 변수를 선언

 

1)    구조체의 정의

u  구조체 멤버(필드) : 구조체를 구성하는 원소

o  배열의 기본 구성단위인 배열 원소에 해당

o  배열원소와 달리 자료형이 서로 달라도 됨

-      배열은 모든 원소가 같은 자료형 -> 기억장소 크기가 같음

-      구조체는 구성하는 멤버가 자료형이 서로 달라도 됨 -> 멤버마다 기억장소 크기 다름

u  구조체의 정의 : 구조체의 구조를 컴파일러에게 알려주는 것

o  템플릿을 정의하는 것! 기억장소를 할당 받는 것이 아님! -> 선언

o  struct : 구조체 예약어.

o  구조체 태그명 : int같은 자료형에 해당한다고 보면 됨. 식별자 생성규칙 따름

o  구조체 정의 마지막에 반드시 “; ”  붙임

o  구조체 태그명과 멤버 명은 달라야 함

o  구조체를 정의하는 위치에 따라 구조체를 자료형으로 사용할 수 있는 범위 결정됨

struct student_info

{         

char name[10];

int grade;

double score[4];

};

- struct : 구조체 표시 예약어

- 구조체 태그명 : 사용자 정의 구조체 자료형 이름

- 자료형 멤버 : 멤버는 선언문 형태로 순서대로 명시

- 멤버 : 변수, 배열, 이미 정의된 다른 구조체 등

- 끝에 반드시 “ ; ” 붙여야 됨

 

2)    구조체 변수 선언

u  구조체에 실제 데이터 저장하기 위해 기억장소를 할당 받는 것

u  struct 구조체 태크명 구조체 변수명;

u  선언 시 주의사항

o  구조체 태그명 앞에 struct 붙이지 않으면 오류 발생

u  선언 위치에 따른 분류

o  지역 변수 : 함수 안에 선언

o  전역 변수 : 함수 밖에 선언

o  정적 변수 : struct 앞에 static 붙임

u  구조체 변수의 선언 위치

o  구조체 템플릿을 정의 한 후 선언

o  구조체 템플릿 정의하면서 동시에 선언 가능

o  구조체 태그명 생략하면 자료형의 이름이 없는 결과 -> 인수나 반환값으로 사용X

 

3)    구조체 멤버 참조

u  멤버 연산자 “ . (dot) ” : 구조체 안의 특정 멤버들을 참조할 때 소속을 밝히는 것

u  구조체 변수명.멤버명

o  구조체 변수명.멤버명; 전체가 한 개의 변수처럼 사용됨

o  scanf( )함수에서 입력값 저장 주소 구하는 & 사용법 : '&구조체 변수명.멤버명

stud.grade = 1;

scanf(“%d”, &stud.name[2]); //배열 원소에 직접 닫닫

scanf(“%d”, stud.name); //배열이름이 포인터!


4)    구조체 변수의 초기화

u  구조체도 변수! 초기화 가능

u  { } 안에 구조체 멤버의 초기값을 “ , (쉼표)”로 구분하여 나열, 순서대로~

 

(1)   구조체 변수를 선언하면서 동시에 초기화하기

o  struct 구조체 태그명 구조체 변수명 = {멤버 초기값1, … 멤버 초기값n};

struct student_info stud01 = { “박보검”, 4, {4.7 , 4.5, 4.3, 4.1}};

o  선언문 끝난 후에는 구조체 변수에 { }를 이용하여 초기화 할 수 없음

멤버 별로 각각 초기화

stud01.grade = 3;

 stud01.score[3] = 4.1; 처럼

 

(2)   구조체 정의, 선언, 초기화 한번에 하기

o  struct 구조체 태그명 ( 자료형 멤버; ,,, 자료형 멤버n; ) } 구조체 변수명 = { 초기값 들 };

o  구조체 변수명 앞에 static 붙이면 정적 변수 됨

struct student_info { 

char name[10];

int grade;

double score[4];

} static stud = = { “박보검”, 4, {4.7 , 4.5, 4.3, 4.1}};

 

5)    구조체 간의 대입

u  같은 구조체형일 경우 하나의 대입문으로 모든 멤버 간 대입 처리

u  구조체형 변수끼리는 구조체 단위로 대입문 사용

(1)   같은 구조체형 변수 간의 대입

o  구조체 변수명 1 = 구조체 변수명 2;

o  struct TV tv1 = {“lg”, 2020, 1900000}, tv2;

tv2 = tv1; // -> tv2.comp = tv1.comp; tv2.year = tv1. year; tv2.price = tv1. price; 와 같음

(2)   동일한 구조체의 템플릿에서 구조체 태그명이 다른 경우의 대입

o  구조체 테그명이 다르면 대입문 사용 X  à  멤버 변수간 대입은 가능


6)    자료형 이름 재정의 : typedef

u  변수를 선언하거나 캐스팅할 때 사용하는 자료형의 이름을 원하는 대로 정의해 사용 가능

u  자료형의 재정의!

u  프로그램의 이식성

u  자료형 이름을 짧게 재정의하거나 읽기 쉽게 함

 

(1)   자료형 이름의 재정의 형식

o  typedef 기존 자료형 이름 새로운 자료형 이름;

o  typedef double REAL;             double avg -> REAL avg;

typedef int* INTP;                 int* ptr -> INTP ptr;

typedef struct person PS;        struct person user -> PS user;

귀찮은 것이 줄어들지

 

(2)   주의사항

o  새로운 자료형 생성 X -> 기존 자료형에 별명을 붙인다! (alias 같이)

o  기본 자료형(int, double, … ) + 사용자 정의 자료형 + 이전 typedef로 재정의한 자료형 적용가능

à 일반 변수명 같은 것은 X

o  #define 전처리기 지시자랑 비교, #define은 컴파일전 처리되고, typedef는 컴파일러가 처리

o  구조체 정의하며 곧바로 typedef로 자료형 재정의 가능

typedef struct point { int x, y, z; } POINT;

POINT p1 = {1, 3, 6}; // = typedef struct point p1 = {1, 3, 6}; 와 같다

 

4.     구조체 배열

1)    구조체 배열 선언

u  자료형 명시하는 자리에 struct 구조체 태그명 써줌

(1)   구조체 배열 선언

o  struct 구조체 태그명 구조체 배열명[원소 개수];

struct person user[100]; // person형 구조체 100개 저장할 배열

struct student_info stud[200]; // student_info형 구조체 200개 저장할 배열

 

(2)   구조체 배열의 선언과 동시에 초기화

o  struct 구조체 태그명 구조체 배열명[원소수] = {{멤버 값1 , … }, {멤버 값1,…}… {멤버 값1…}};

struct person user[100]={{“박보검”, “”, 26}, {“서강준”, ””, 26}, .. {“축복의”, ”1993”, 26}};

 

(3)   초기화할 때 주의 사항

o  마지막 멤버들은 생략 가능해도 중간 멤버들은 생략이 안된다! 순서대로~

o  struct person user[100]={{“박보검” }, {“서강준”, ””}, .. {“축복의”, ””, 26}};

맨 끝 값들은 생략되고  이렇게 중간은 안됨

 

2)    구조체 배열 원소와 멤버 참조

u  구조체 배열명[첨자].멤버명

user[0].age=20; / user[99].age=25; / stud[53].score[3] = 4.5;

 

5.     구조체 포인터

n  구조체로 저장된 데이터를 가리키는 구조체 포인터!

n  연결리스트, 트리 같은 자료구조 구현하는데 사용됨

n  다른 포인터들과 같이 4byte!

 

1)    구조체 포인터 선언

(1)   구조체 포인터 선언하기

o  구조체 포인터가 가리키는 곳에 구조체가 있다면 구조체 태그명 명시!

o  struct 구조체 태그명 * 구조체 포인터명;

-      구조체 포인터가 가리키는 곳에 구조체 태그명의 구조체가 있음을 의미

-      struct person *ptr

person형 구조체가 저장된 곳의 시작주소가 ptr에 저장됨

(2)   포인터가 구조체를 가리키게 하기

o  구조체의 시작 주소를 구조체 포인터 변수에 대입

o  구조체 포인터 변수명 = &구조체 변수명;

-      포인터 변수에 구조체 변수의 시작주소를 대입

-      자료형이 일치해야 함! 같은 구조체 태그명!

-      ptr = $stud1;

 

2)    구조체 포인터를 사용한 간접 참조

(1)   *(간접참조연산자) .(멤버연산자) 이용

o  (*구조체 포인터 변수명).멤버명

구조체 포인터 변수가 가리키는 구조체의 멤버!

( )생략하면 오류 발생 -> 간접참조연산자 * 보다 멤버 연산자 . 이 우선순위가 높음

o  (*ptr).age=20;.

scanf(“%s”, (*ptr).name);          scanf(“%d”, &(*ptr).age);

scanf(“%s”, ptr à name);        scanf(“%d”, &ptr à age);

 

(2)   à이용한 포인터

o  구조체 포인터 변수명 à 멤버명

o  printf(“%d”, &ptr à age);

scanf(“%s”, ptr->name);

ptr à age = 30;

6.     함수 간의 구조체 전달

1)    값에 의한 호출

u  함수가 호출되면 매개변수는 구조체에 해당하는 기억 공간 할당 받음 -> 인수의 각 멤버 값이 매개변수 멤버 값으로 복사 됨

u  호출 : 함수명 (구조체 인수명)  à  정의 : 반환형 함수형 (struct 구조체 태그명 매개변수명) { }

 

2)    주소에 의한 호출

u  구조체의 시작 주소 전달! à 매개변수를 포인터로 선언! 매개변수로 구조체 주소번지를 받음

u  호출 : 함수명(&구조체 인수명) 

à  정의 : 반환형 함수명(struct 구조체 태그명 *매개변수명) {

매개변수명 à 멤버명 사용해서 멤버 참조  }

                      scanf(“%s”, ptr à name);             scanf(“%d”, &ptr à age);

 

3)    구조체 배열 전달

(1)   배열 선언 방식

o  함수를 정의할 때 매개변수를 배열로 선언 -> 배열명이 포인터 변수로 사용되는 것

o  호출 : 함수명(구조체 배열명)  à  정의 : 반환형 함수명(struct 구조체 태그명 배열명[]){ }

 

(2)   포인터 선언 방식

o  호출 : 함수명(구조체 배열명)

 à  정의 : 반환형 함수명(struct 구조체 태그명 *포인터 변수명){ }

 

2절  공용체와 열거형

1.     공용체

n  같은 메모리 영역을 여러 개의 변수들이 공유할 수 있게 하는 기능 -> 메모리 절약 위해

n  union 예약어에 공용체 태그 사용

n  멤버들이 같은 공간 공유 -> 동시에 멤버 변수들의 값을 저장할 수 없으면 어떤 순간에는 하나의 멤버만 존재할 수 있음!

n  가장 큰 멤버의 크기만큼 메모리 할당 받음

 

1)    공용체 선언

u  공용체 변수의 크기 = 크기가 가장 큰 멤버의 크기

u  한 공간을 두 개 이상의 변수가 공유하므로 예기치 않은 결과 나올 수 있음

덮어쓴다거나 하는 거지. 두 공간 공유 못하면 뒤에 들어온 애가 맨 앞 메모리 차지함..

u  union 공용체 태그명 { 자료형 멤버명 … } ; //정의

union 공용체 태그명 공용체 변수명; // 선언

 

2)    공용체 변수 초기화

u  공용체 변수 초기화 시 중괄호 사용해 첫 번째 멤버만 초기화

u  첫 번째 멤버 아닌 멤버 초기화 시 멤버연산자로 직접 지정해 초기화

u  union 공용체 태그명 공용체 변수명 = { 123 }; // 첫 번째 멤버 초기화

union 공용체 태그명 공용체 변수명 = {.멤버명 = 123 };

                      공용체 변수명.멤버명 = 123;

 

2.     열거형

n  변수가 가질 수 있는 값들을 나열한 자료형 -> 변수가 가질 수 있는 상수들의 모임

n  열거형으로 선언된 변수는 열거형에 정의된 상수만 값으로 가짐

-> 프로그램에서 가질 수 있는 값을 제한하는 것

 

1)    열거형의 정의와 선언

(1)   열거형의 정의

o  예약어 enum, 사용자가 새로운 자료형을 정의

o  enum 열거형 태그 { 열거형 변수에 저장 가능한 기호화된 정수 값들 };

o  enum days {SUN, MON, TUE, THU, FRI, SAT};

 

(2)   열거형의 선언

o  enum 열거형 태그 열거형 변수; // 선언

열거형 변수 = 기호상수 ; // 초기화

enum days today;

today = My_Day;  -- 오류 --> today = MON;

 

2)    기호상수들의 값

u  열거형 안에 들어 있는 상수들은 0에서 시작하여 1씩 증가하는 정수 값. -> 자동으로 설정됨

enum days {SUN, MON, TUE, THU, FRI, SAT};

SUN = 0, MON = 1, … 이런 식

u  값 배정은 변경 가능. 식별자 뒤에 시작하는 숫자를 넣어주면 됨

u  enum days {SUN=1, MON, TUE=5, THU, FRI, SAT=3};

SUN =1 이므로 MON =2로 자동 설정됨

TUE =5 이므로 THU =6, FRI = 7로 자동 설정됨

SAT = 3 이므로 SAT 3

 

3)    다른 방법과의 비교

u  열거형은 정수 형태의 기호 상수를 정의

특정 숫자 대신 기호를 사용함으로써 프로그램 이해도 향상

변수가 열거된 값 이외의 값을 취하는 것을 막아 오류 감소

 

3절  동적 기억장소 할당

1.     정적 할당과 동적 할당

n  정적 할당은 기억장소 낭비할 수 있음

 

2.     정적 할당

n  전역 변수, 정적 변수! 지역변수도 일종의 정적 할당

n  프로그램 컴파일 할 때 할당 받을 기억장소의 크기를 결정하고 프로그램 실행 시작 전에 이미 정적으로(statically), 고정된 크기로 프로그램 실행 끝까지 기억장소 할당 받음

n  프로그램 실행 끝나면 기억장소 해제됨

n  지역변수 ! 프로그램 실행 동안 함수 호출 되면 스택 영역에 기억장소 받지만 (동적인 것 같지만) 크기가 컴파일 시점에서 이미 결정되어있음! 고정된 크기로 할당 받는 것 -> 정적 할당에 해당

n  정적 할당의 문제점

u  할당된 공간 이상을 사용하는 것이 불가능함 (배열 크기 선언 시 변수가 안됨..)

u  공간을 매우 크게 할당 받으면 메모리 낭비가 심함

 

3.     동적 할당

n  프로그램 실행 동안 기억장소 필요 시점에서 필요한 만큼만 요청하여 할당 받음

n  힙 영역의 일부를 시스템에서 기억장소로 제공

n  주기억장치의 네 가지 영역

    코드 영역

cpu에게 내리는 명령어 코드

    데이터 영역

전역 변수와 정적 변수

    힙 영역

동적으로 할당할 기억 장소

    스택 영역

함수의 매개변수와 지역 변수

 

1)    동적 할당 함수 : malloc() 함수

u  동적으로 기억장소 할당 받아 사용하려면 포인터 변수와 malloc()함수 이용

u  포인터 변수 : 동적으로 할당 받은 기억장소의 시작주소 저장에 사용

u  포인터가 할당 받은 기억장소 가리키게 되면 그 다음부터 포인터 변수를 일반 배열명처럼 또는 실제 포인터 변수로서 활용하여 기억장소 참조!

u  자료형 * 포인터 변수명;

포인터 변수명 = (자료형 *) malloc (기억장소 크기 : byte단위)

o  malloc (기억장소 크기)

-      지정한 크기의  기억장소 할당 받아 시작 주소 반환

-      #include<stdlib.h> 추가

-      보통 malloc( sizeof (자료형)*필요 개수)식으로 자료형의 크기를 연산해서 씀

int a[20] 배열이면 sizeof(int)*20을 써주는 것!

이식성을 위해서걍 상수 20 이렇게 하면 시스템마다 크기가 다를 수 있음

-      힙 영역에 할당 가능한 기억장소 없으면 malloc()함수는 NULL매크로 상수 반환

-> 반드시 요청 후 할당 여부 확인! 권장

o  (자료형 *)

-      동적 할당 기억장소의 시작주소를 저장한 자료형의 포인터로 캐스팅함

-      malloc()함수가 할당 받은 기억장소 시작 주소를 void형 포인터로 반환하기에 캐스팅!

-      기억장솨를 용도에 맞게 저장할 자료형 공간으로 캐스팅해야 함

 

2)    동적 할당 기억장소 해제 함수 : free() 함수

u  지역변수는 함수 실행 끝나면 자동으로 기억장소가 해제됨 -> 자유상태

u  동적으로 할당 받은 기억 장소는 함수 실행 끝나도 자동으로 해제되지 않음

u  자유 상태 되도록 직접 해지!

u  free(포인터 변수명);

free(ptr); // ptr = (int*)malloc(sizeof(int));로 할당 받은 기억장소 해제

free(ch); // ptr = (int*)malloc(sizeof(chat)*10));로 할당 받은 기억장소 해제(char형 배열 10개짜리)

 

3)    동적 할당 관련 함수

 

 


+ Recent posts