본문 바로가기

Daylogs/C

C: 구조체와 typedef




구조체(Structure)

하나 이상의 변수를 묶어 새로운 자료형을 정의하는 도구

struct type_name
{
  멤버 선언;
};


구조체 변수 선언
struct type_name val_name;

구조체 멤버를 가져올 때엔
val_name.member_name 으로.

struct point
{
  int x;
  int y;
};

초기화는 배열과 동일한 방식으로 할 수 있다.
struct point = { 10, 20 };

구조체 멤버 중에 배열이나 포인터 변수가 있을 경우, 포인터 변수의 접근 방식을 취한다.

struct person
{
  char name[20];
  int age;
};

struct person man;
strcpy(man.name, "새이름"); // 새 주소가 할당되지 않게 값을 복사한다.
man.age = 10;

struct person man2 = { "다른이름", 20 }; // 선언과 동시에 초기화하는 경우는 문제 없다.



구조체 배열

struct point thepoint = { 10, 20 }; // point 형의 변수 선언
struct point *p = &thepoint; // 구조체를 가리키는 포인터

(*p).xpos = 30; // 구조체 멤버를 포인터로 접근해 설정
p->xpos = 30; // 포인터 p가 가리키는 구조체 변수의 멤버에 30 저장
                      // 즉, *와 . 연산을 -> 하나의 연산으로 대신할 수 있다.


구조체 변수를 멤버로 가질 수 있다.
struct circle
{
  double radius;
  struct point * center;
}

struct circle c = { 10.0, &thepoint };
circle.c -> xpos;


구조체 변수의 주소값은, 첫 번째 멤버의 주소와 동일하다.


타입형 구조체 변수의 멤버로 타입형 포인터 변수를 둘 수도 있다.
struct point
{
  int xpos;
  int ypos;
  struct point * ptr;
}



typedef 

typedef = 기존에 존재하는 자료형에 새 이름을 부여
typedef 자료형 새이름; 

typedef 로 정의하는 자료형의 이름은 대문자로 시작하는 것이 관례

typedef int * PTR_INT; // int형 포인터를 PTR_INT라는 타입으로 정의한다.
typedef struct point Point; // struct point에 Point라는 이름 부여

Point p1;


타입 선언과 구조체 정의를 한 번에 묶을 수 있다.
typedef struct point
{
  int x;
  int y;
} Point;

!! 실제로 typedef 선언이 구조체 선언보다 먼저 와도 괜찮다.
typedef abbdd Efwdf; // 존재하지 않는 타입을 선언해도 컴파일 에러는 발생하지 않는다.

구조체 이름을 생략할 수도 있다.
typedef struct 
{
  int x;
  int y;
} Point;



함수로의 구조체 변수 전달과 반환

함수의 인자로 구조체 변수를 전달할 수 있으며, 인자를 전달받을 수 있도록 구조체 변수가
매개변수의 선언으로 올 수 있다.
그리고 전달되는 구조체 변수의 값은 매개변수에 통째로 "복사"된다.

즉, 기본적으로 구조체는 매개변수로 전달되거나, 함수에서 반환될 때, Call-by-value 형태로 구현된다.

printPoint(p); // 복사된다.

구조체 포인터를 사용할 경우, Call-by-reference 형태로 사용할 수 있다.

printOriPoint(&p); // 포인터를 전달한다.

구조체 변수간 대입 연산을 할 경우에도 멤버 대 멤버의 복사가 이뤄진다.

Point p = { 10, 20 };
Point p2 = p; // 복사된다.


구조체를 중첩으로 사용할 수 있다. 물론!



공용체(Union Type)의 정의와 의미

typedef union ubox
{
  int mem1;
  int mem2;
  double mem3;
} UBox;

구조체와 선언 방법은 거의 동일하고 struct 대신 union 키워드를 사용한다.
동일한 메모리 공간에 대해 여러 가지 접근법을 제시한다!!



열거형(Enumerated Type)의 정의와 의미

변수에 저장이 가능한 값들을 열거하여 정의한다고 해서 '열거형'이라고 한다.
열거형은 저장이 가능한 값 자체를 정수의 형태로 결정한다.

enum syllable // syllable이라는 이름의 열거형 정의
{
  Do=1, Re=2, Mi=3, Fa=4, So=5, La=6, Ti=7
};


값을 할당하지 않고 정의할 수도 있다.

enum color {RED, BLUE, WHITE, BLACK};
                      0      1         2          3   // 0부터 순서대로 할당된다.


열거형의 유용함은 이름있는 상수 정의를 통한 의미 부여에 있다.
즉, 둘 이상의 연관이 있는 이름을 상수로 선언함으로써 프로그램의 가독성을 높이는데 있다.
따라서, 다음과 같이 자료형의 이름을 생략한 형태로 열거형을 정의할 수도 있다.

enum { DO=1, Re=2, Mi=3 };

Do, Re, Mi는 각각 상수로써의 의미를 지닌다.





다음 글: 9. 파일 입출력