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) 동적 할당 관련 함수
'[시험] 독학사 2020 전공기초' 카테고리의 다른 글
[독학사][컴퓨터 시스템 구조] 01 컴퓨터 시스템 개요 (0) | 2020.05.01 |
---|---|
[독학사][C프로그래밍] 08 파일처리함수 (0) | 2020.04.28 |
[독학사][C프로그래밍] 06 배열과 포인터 (0) | 2020.04.28 |
[독학사][C프로그래밍] 05 함수와 기억클래스 (0) | 2020.04.28 |
[독학사][C프로그래밍] 04 제어문 (0) | 2020.04.28 |