728x90
자료형
- 기초자료형; int, char, double, void …
- 파생자료형; 배열, 포인터, 구조체, 공용체
- 사용자정의 자료형; typedef, enum
배열과 달리 사이즈나 자료형 달라도 됨
구조체의 이름(:태그) ; 변수명이 아님 ← 틀만 만들 땐 메모리 할당 안 됨
안에 변수를 적어야 할당됨
struct 구조체명 { //구조체 선언
// 멤버들
int number; // 1000
char name[10]; // 1004
double grade; // 1014
}; // 마지막에 세미콜론 o
구조체의 초기화
struct student s1 = {24, "Kim", 4.3};
구조체 멤버 참조
s1.grade = 3.8;
예제1
#include <stdio.h>
struct student { //구조체 정의
int number;
char name[10];
double grade;
};
int main(void)
{
struct student s; //구조체 변수 선언
s.number = 20190001; //구조체 멤버 참조
strcpy(s.name, "홍길동");
s.grade = 4.3;
printf("학번: %d\\n", s.number);
printf("이름: %s\\n", s.name);
printf("학점: %.2f\\n", s.grade);
printf("%p\\n", & s.number); //00000058354FFC58
printf("%p\\n", &s.name); //00000058354FFC5C. 58+4 = 5C
printf("%p", &s.grade); //00000058354FFC68 5C+10(A) = 66, but 4byte씩 패킹돼서 5C+12(C)= 68
return 0;
}
💡 #pragma pack(1) ; 4byte씩이 아니라 꽉 눌러담고 싶을 때
레지스터 access할 때도 써야 할 때 있음
두 점 사이 거리 구하기
#include <math.h>
#include <stdio.h>
struct point {
int x;
int y;
};
int main(void)
{
struct point p1, p2;
int xdiff, ydiff;
double dist;
printf("점의 좌표를 입력하시오(x y): ");
scanf_s("%d %d", &p1.x, &p1.y);
printf("점의 좌표를 입력하시오(x y): ");
scanf_s("%d %d", &p2.x, &p2.y);
xdiff = p1.x - p2.x;
ydiff = p1.y - p2.y;
dist = sqrt((double)(xdiff * xdiff + ydiff * ydiff));
printf("두 점 사이의 거리는 %f입니다.\\\\n", dist);
return 0;
}
구조체를 멤버로 갖는 구조체 있을 수 ㅇ
#include <stdio.h>
struct point{
int x;
int y;
};
struct rect{
struct point p1;
struct point p2;
};
int main(void)
{
struct rect r;
int w, h, area, peri;
printf(”왼쪽 상단의 좌표를 입력하시오: “);
scanf(”%d %d”, &r.p1.x, &r.01.y);
printf(”오른쪽 상단의 좌표를 입력하시오: “);
scanf(”%d %d”, &r.p2.x, %r.p2.y);
w = r.p2.x - r.p1.x;
h = r.p2.x - r.p1.x;
area = w * h;
peri = 2 * w + 2 * h;
printf(”면적은 %d이고 둘레는 %d입니다.\\n”, area, peri);
return 0;
}
같은 구조체 변수끼리 대입 가능, 비교는 불가능(멤버들끼리 비교해야)
struct point {
int x;
int y;
};
int main(void)
{
struct point p1 = { 10, 20 };
struct point p2 = { 30, 40 };
p2 = p1; // 대입 가능, 주소는 다르고 값만 대입됨
if (p1 == p2) //비교 -> 컴파일 오류!!
printf("p1와 p2이 같습니다.");
if ((p1.x == p2.x) && (p1.y == p2.y)) //올바른 비교
printf("p1와 p2이 같습니다.");
}
구조체와 포인터
- 구조체를 가르키는 포인터
- 포인터를 멤버로 가지는 구조체
struct student s = {24, "Kim", 4.3};
struct student *p;
p = &s;
printf("학번=%d, 이름=%s, 학점=%f\\n", s.number, s.name, s.grade);
printf("학번=%d, 이름=%s, 학점=%f\\n", (*p).number, (*p).name, (*p).grade);
#include <stdio.h>
#define SIZE 3
struct student {
int number;
char name[20];
double grade;
};
int main(void)
{
struct student list[SIZE];
for (int i = 0; i < SIZE; i++)
{
printf("학번을 입력하시오: ");
scanf_s("%d", &list[i].number);
printf("이름을 입력하시오: ");
scanf_s("%s", list[i].name, 20); //scanf_s 문자열은 사이즈 지정 필요
printf("학점을 입력하시오(실수): ");
scanf_s("%lf", &list[i].grade);
}
for (int i = 0; i < SIZE; i++)
printf("학번: %d, 이름: %s, 학점: %f\\n", list[i].number, list[i].name, list[i].grade);
struct student s = { 24,"Kim", 4.3};
struct student* p;
p = &s;
printf("학번=%d 이름=%s 학점=%f \\n", s.number, s.name, s.grade);
printf("학번=%d 이름=%s 학점=%f \\n", (*p).number, (*p).name, (*p).grade);
printf("학번=%d 이름=%s 키=%f \\n", p->number, p->name, p->grade); //많이 씀!!!!!!
return 0;
}
구조체의 포인터를 함수의 인수로 전달하는 경우
- 시간, 공간 절약 o
- 원본 훼손의 가능성 o
값으로 함수의 인수 전달
#include <stdio.h>
struct vector {
float x;
float y;
};
struct vector get_vector_sum(struct vector a, struct vector b);
int main(void)
{
struct vector a = { 2.0, 3.0 };
struct vector b = { 5.0, 6.0 };
struct vector sum;
sum = get_vector_sum(a, b);
printf("벡터의 합은 (%f, %f)입니다.\\n", sum.x, sum.y);
return 0;
}
struct vector get_vector_sum(struct vector a, struct vector b)
{
struct vector result;
result.x = a.x + b.x;
result.y = a.y + b.y;
return result;
}
공용체
같은 메모리 영역을 여러 변수가 공유 (덮어둠)
선언, 사용법은 구조체와 비슷
union example{
char c; //주소 0x100이면
int i; //얘도 주소 0x100
}; //구조체면 다음 주소에 되지만, 공용체는 같은 주소
#include <stdio.h>
union example {
int i;
char c;
};
int main(void)
{
union example v;
v.c = 0x01;
printf("v.c:%c v.i:%x\\n", v.c, v.i);
v.i = 0xABCDEF7A;
printf("v.c:%c v.i:%i\\n", v.c, v.i);
return 0;
}
열거형 enum
- 변수가 가질 값들을 미리 열거
- 0부터 1, 2, 3, …
int today;
today = 0; //일요일
today = 1; //월요일
- 오류 줄이고 가독성 높이기
- 0보단 SUN 기호상수가 더 적절
- today에 9 같은 의미없는 값 대입 안 되도록 미리 차단해주기
예제
#include <stdio.h>
enum days { SUN, MON, TUE, WED, THU, FRI, SAT};
char* days_name[] = { //문자열의 배열
"sunday", "monday", "tudesday", "wednesday", "thursday",
"friday", "saturday" };
int main(void)
{
enum days d;
d = WED; //d에 3들어감 -> 3번째 배열
printf("%d번째 요일은 %s입니다.\\n", d, days_name[d]);
return 0;
}
typedef
- 기존의 자료형에 새로운 자료형 BYTE로 정의
- typedef (기존)unsigned char (새로운)BYTE;
정수 사용 | 기호 상수 | 열거형 |
switch(code) { case 1: printf(”LCD TV \n”); break; case 2: printf(”OLED TV\n”); break; } |
#define LCD 1 #define OLED 2 switch(code){ case LCD: printf(”LCD TV\n”); break; case OLCD: printf(”OLED TV\n”); break; } |
enum tvtype { LCD, OLED}; enum tvtype code; switch(code) { case LCD: printf(”LCD TV\n”); break; case PDP: printf(”OLED TV\n”); break; } |
컴퓨터는 쉬우나, 사람은 기억 하기 어렵 | 기호 상수 작성 시 오류 저지를 수도 | 컴파일러가 중복 안 일어나게 체크 |
#include <stdio.h>
typedef struct point { //태그 안 써도 되나봄
int x;
int y;
} POINT;
/* //위와 동일, but 위가 더 자주 씀
struct point{
int x;
int y;
};
typedef struct point POINT;
*/
POINT translate(POINT p, POINT delta);
int main(void)
{
POINT p = { 2, 3 };
POINT delta = { 10, 10 };
POINT result;
result = translate(p, delta);
printf("새로운 점의 좌표는(%d, %d)입니다.\\n", result.x, result.y);
return 0;
}
POINT translate(POINT p, POINT delta)
{
POINT new_p;
new_p.x = p.x + delta.x;
new_p.y = p.y + delta.y;
return new_p;
}
공용체에 타입필드 사용
#include <string.h>
#define STU_NUMBER 1
#define REG_NUMBER 2
struct student {
int type;
union {
int stu_number;
char reg_number[15];
} id;
char name[20];
};
void print(struct student s)
{
switch (s.type)
{
case STU_NUMBER:
printf("학번 %d\\n", s.id.stu_number);
printf("이름: %s\\n", s.name);
break;
case REG_NUMBER:
printf("주민등록번호: %s\\n", s.id.reg_number);
printf("이름: %s\\n", s.name);
break;
default:
printf("타입오류\\n");
break;
}
}
int main(void)
{
struct student s1, s2;
s1.type = STU_NUMBER;
s1.id.stu_number = 20190001;
strcpy(s1.name, "홍길동");
s2.type = REG_NUMBER;
strcpy(s2.id.reg_number, "860101-1056076");
strcpy(s2.name, "김철수");
print(s1);
print(s2);
return 0;
}
728x90
'Programming > C' 카테고리의 다른 글
16. 전처리 및 다중 소스 파일 (1) | 2023.10.19 |
---|---|
15. 스트림과 파일 입출력 (1) | 2023.10.19 |
12. 문자열 (0) | 2023.10.19 |
11. 포인터 (1) | 2023.10.19 |
10. 배열 (0) | 2023.10.19 |