
typedef → "type + definition"으로, 그대로 해석하면 형을 정의하는 것이라 할 수 있다. 정확히는 이미 존재하는 자료형의 이름을 자신이 만든 이름으로 바꾸거나, 구조체형을 선언할 때 사용한다.
⌨️ 예제 1
#include <stdio.h>
int main() {
// 자료형의 이름 변경
typedef float Decimal; // 기존 float형의 이름을 decimal이라는 새로운 이름으로 변경
Decimal n = 3.14;
printf("%f\n", n);
// 배열의 이름 변경(요소 2개가 점의 x, y좌표를 가리키는 순서쌍을 의미하는 배열)
typedef int Pair[2]; // 길이 2짜리 int형 배열의 이름을 Pair로 붙임([2] 포함)
Pair point = {3, 4}; // == int point[2] = {3, 4}; ([2]를 적으면 안 됨)
printf("(%d, %d)\n",point[0], point[1]);
// 포인터의 이름 변경
typedef char *String; // 문자열의 주소를 저장하는 char형 포인터의 이름을 String으로 붙임(* 포함)
String name = "JY"; // == char *name = "JY"; (*를 적으면 안 됨)
printf("이름 : %s\n", name);
}
🖥️ 실행 결과
3.140000
(3, 4)
이름 : JY
구조체는 (서로 다른 자료형인)여러 개의 변수를 모아서 하나의 새로운 자료형으로 정의하는 것이다. struct라는 구조체 지정자와 사용자가 붙이는 구조체명(structure tag)을 합하여 구조체형을 정하고, 구조체에 속하는 변수들을 구조체 멤버로 기술한다.
⌨️ 예제 2
// 구조체 정의와 구조체 변수 선언 → 예약어 typedef 사용한 방법
#include <stdio.h>
int main() {
// 구조체 정의 → 중괄호 안에 구조체 멤버들의 자료형과 이름 나열
typedef struct {int x, y;} Point; // 구조체 멤버 x, y를 묶어서 Point형으로 정의한다는 뜻
// 구조체 변수 선언
Point p; // == struct {int x, y;} p;
// 구조체 멤버의 참조 → 멤버 연산자 도트(.)를 사용
p.x = 3; // 구조체 멤버 x애 3 대입
p.y = 4; // 구조체 멤버 y에 4 대입
printf("(%d, %d)\n", p.x, p.y); // 순서쌍의 형태로 출력됨
}
// 구조체 정의와 구조체 변수 선언 → typedef 사용하지 않는 방법
#include <stdio.h>
// 구조체 정의와 구조체 변수 선언을 동시에 가능
struct Point {int x, y;} p; // 구조체는 주로 전역변수로 정의된다
int main() {
// 구조체 멤버의 참조
p.x = 3;
p.y = 4;
printf("(%d, %d)\n", p.x, p.y);
}
// 구조체 정의와 구조체 변수 선언 → 변수의 초기화까지 하는 방법
#include <stdio.h>
struct Point {int x, y;}; // 구조체 정의
struct Point p = {3, 4}; // 구조체 변수 선언과 초기화(배열의 초기화와 같은 방법)
int main() {
printf("(%d, %d)\n", p.x, p.y);
}
🖥️ 실행 결과
(3, 4)
구조체를 만드는 방법에는 여러 가지가 있으며, 실행 결과는 동일하다.
예제에서 p는 Point형을 가진 구조체 변수다. 구조체 변수 p를 선언하는 것은 p에 int형 2개 크기(8byte)의 기억공간을 할당한다는 것을 뜻한다.
⌨️ 예제 3
#include <stdio.h>
struct ProductInfo { // 구조체 안에 다양한 형의 변수(멤버)들 나열 가능
int num;
char name[100];
int cost;
};
int main() {
struct ProductInfo myProduct = {355, "샤인머스캣", 19900}; // 구조체 멤버 나열 순
printf("상품 번호 : %d\n", myProduct.num);
printf("상품 이름 : %s\n", myProduct.name);
printf("상품 가격 : %d원\n", myProduct.cost);
}
🖥️ 실행 결과
상품 번호 : 355
상품 이름 : 샤인머스캣
상품 가격 : 19900원
구조체 포인터는 포인터명 앞에 *를 붙여서 선언하고, 구조체 변수의 주소값(구조체 변수 앞에 &)으로 초기화한다. 일반 포인터와 동일하게 주소값을 갖고, 자료가 있는 곳을 가리킨다.
⌨️ 예제 4
// 예제 3에 구조체 변수를 가리키는 구조체 포인터 추가
#include <stdio.h>
struct ProductInfo {
int num;
char name[100];
int cost;
};
int main() {
struct ProductInfo myProduct = {355, "샤인머스캣", 19900}; // 구조체 변수 선언, 초기화
struct ProductInfo *ptr_product = &myProduct; // 구조체 포인터 선언, 초기화
// 구조체 포인터의 멤버 참조 2가지 방법
printf("상품 번호 : %d\n", (*ptr_product).num); // 도트 연산자(.)
printf("상품 이름 : %s\n", ptr_product -> name); // 포인터 연산자(->)
printf("상품 가격 : %d원\n", ptr_product -> cost);
}
🖥️ 실행 결과
상품 번호 : 355
상품 이름 : 샤인머스캣
상품 가격 : 19900원
구조체 포인터로 멤버를 참조할 때 구조체 연산자인 도트 연산자를 이용하거나 포인터 연산자를 이용할 수 있다. 도트 연산자를 이용하는 경우에는 .가 *보다 연산 순서상 먼저인데, *를 먼저 계산해야 하므로, 괄호를 꼭 사용해야 한다.
⌨️ 예제 5
// call-by-reference로 매개변수의 자료 전달
#include <stdio.h>
struct ProductInfo {
int num;
char name[100];
int cost;
};
void productSale(struct ProductInfo *p, int percent) { // 가격에 n% 할인을 적용하는 함수
p->cost -= p->cost * percent / 100; // 할인가 = 원가 - 원가 × 할인률(%)/100
}
int main() {
struct ProductInfo myProduct = {355, "샤인머스캣", 20000};
productSale(&myProduct, 10); // myProduct의 주소값 넘겨주고 percent에 10 대입
printf("상품 번호 : %d\n", myProduct.num);
printf("상품 이름 : %s\n", myProduct.name);
printf("상품 가격 : %d원\n", myProduct.cost);
}
🖥️ 실행 결과
상품 번호 : 355
상품 이름 : 샤인머스캣
상품 가격 : 18000원
10% 할인된 가격이 적용됐다.
이와 같이 함수를 사용할 때 함수의 매개변수로 구조체를 사용할 수 있다. 크게 구조체 자체를 함수의 매개변수로 사용하는 방법과 구조체 포인터를 함수의 매개변수로 사용하는 방법으로 나뉘는데, 구조체 포인터를 사용하면 구조체를 복사하지 않아도 되기 때문에 주로 이 방법을 많이 사용한다.
⌨️ 예제 6
// 2개의 구조체 포인터를 매개변수로 받아 값을 서로 바꾸는 함수
#include <stdio.h>
struct ProductInfo {
int num;
char name[100];
int cost;
};
void productSwap(struct ProductInfo *a, struct ProductInfo *b) { // 두 상품의 가격을 교환
struct ProductInfo tmp = *a; // a가 가리키는 값을 임시변수 tmp에 저장
*a = *b; // a가 가리키는 구조체 변수에 b가 가리키는 구조체 변수를 대입
*b = tmp; // b가 가리키는 구조체 변수에 tmp 값 저장
}
int main() {
struct ProductInfo myProduct = {355, "샤인머스캣", 20000}; // 구조체 변수 선언, 초기화
struct ProductInfo otherProduct = {356, "납작복숭아", 10000};
productSwap(&myProduct, &otherProduct); // 참조 호출(& 사용)
printf("상품 번호 : %d\n", myProduct.num);
printf("상품 이름 : %s\n", myProduct.name);
printf("상품 가격 : %d원\n", myProduct.cost);
}
🖥️ 실행 결과
상품 번호 : 356
상품 이름 : 납작복숭아
상품 가격 : 10000원
myProduct에 들어있던 "샤인머스캣"이라는 상품의 정보가 "납작복숭아"라는 상품의 정보로 바뀌었다.
⌨️ 예제 7
#include <stdio.h>
typedef int Point[2]; // 길이 2인 int형 배열을 Point형으로 선언
typedef Point *PointPtr; // Point형 배열을 가리키는 포인터를 PointPtr형으로 선언
int main() {
Point p = {3, 4}; // == int p[2] = {3, 4};
PointPtr pp = &p; // == Point *pp = &p;
printf("%d %d %d\n", **pp, (*pp)[0], (*pp)[1]);
}
🖥️ 실행 결과
3 3 4
**pp == *(*pp) == *p == p[0] → 3 출력
(*pp)[0] == p[0] → 3 출력
(*pp)[1] == p[1] → 4 출력
C에서는 불가능하지만 C++에서는 구조체 안에 함수를 정의할 수 있다.
⌨️ 예제 8
C 언어
// 시간을 초로 계산하는 프로그램(1시간 = 60분 = 3600초)
#include <stdio.h>
struct Time {
int h, m, s;
};
int totalSec(struct Time t) {
return (3600 * t.h) + (60 * t.m) + t.s;
}
int main() {
struct Time t = {1, 15, 30};
printf("%d\n", totalSec(t));
}
C++ 언어
#include <stdio.h>
struct Time {
int h, m, s;
// 구조체 내에 멤버 함수 선언(구조체 안의 다른 변수들에 접근 가능하므로 매개변수 필요 없어짐)
int totalSec() {
return (3600 * h) + (60 * m) + s; // 변수 h, m, s를 그대로 사용 가능해짐
}
};
int main() {
Time t = {1, 15, 30};
printf("%d\n", t.totalSec()); // 구조체의 멤버 함수에 접근 가능
}
🖥️ 실행 결과
4530
Time이라는 구조체 안에 totalSec 함수를 넣어서 totalSec는 Time에 종속적인 관계라는 것을 명확하게 알 수 있는 방법이다.
⌨️ 예제 9
C++ 언어
#include <stdio.h>
struct Point {
int x, y;
// 구조체 안에 상하좌우로 움직이는 멤버 함수 선언
void moveRight() {x++;}
void moveLeft() {x--;}
void moveUp() {y++;}
void moveDown() {y--;}
};
int main() {
Point p = {2, 5}; // 점의 초기 좌표 설정
p.moveDown();
p.moveLeft();
printf("(%d, %d)\n", p.x, p.y); // 이동 후 점의 좌표 출력
}
🖥️ 실행 결과
(1, 4)
⌨️ 예제 10
C 언어
// x좌표와 y좌표를 교환
#include <stdio.h>
struct Point {int x, y;};
void pSwap(struct Point *p) {
int tmp = p->x; // 포인터 변수가 구조체 멤버에 접근하기 위해 연산자 사용
p->x = p->y; // p의 y 값을 p의 x에 대입
p->y = tmp;
}
int main() {
struct Point pos = {3, 4};
pSwap(&pos);
printf("(%d, %d)\n", pos.x, pos.y);
}
C++ 언어
#include <stdio.h>
struct Point {
int x, y;
void pSwap() { // pSwap 함수를 구조체 안에 선언
int tmp = x;
x = y;
y = tmp;
}
};
int main() {
struct Point pos = {3, 4};
pos.pSwap();
printf("(%d, %d)\n", pos.x, pos.y);
}
🖥️ 실행 결과
(4, 3)