Study/C,C++

7. 구조체

MeditT 2018. 7. 22. 20:08

구조체

구조체: 여러 개의 데이터를 그룹으로 묶어서 하나의 자료형으로 정의하고 사용하는 자료형. 서로 다른 타입끼리 묶을 수 있다.

구조체의 구조

  • 레코드(Record): 구조체의 단위 형식

  • 필드(Field): 레코드를 구성하는 하위 항목

  • 파일(File): 레코드의 묶음. 하나의 구조체 통째.

표를 예로 들어보면, 표 하나 통째는 파일, 표 한 줄은 레코드, 표 한 칸은 필드가 된다.


구조체의 선언 & 초기화

  struct 구조체이름
{
   타입 이름1;
   타입 이름2;
  ...
   타입 이름n;
};

이건 구조체를 선언만 한 것이고, 사용하려면 구조체 변수를 또 다시 선언해야 한다.


struct 구조체이름 구조체변수이름;

이렇게 변수 이름을 선언해주어야 비로소 사용할 수 있게 된다.


* 구조체의 선언과 구조체 변수 이름의 선언을 함께 할 수도 있다. 구조체이름을 생략하고 변수이름만 선언도 가능하다.

  //구조체 선언 + 구조체 변수 이름의 선언을 동시에.

struct Tire
{
   int 앞바퀴;
   int 뒷바퀴;
} 금호; //금호라는 이름의 Tire변수를 선언.


구조체의 초기화

  
struct Tire 금호 = {2, 2}; //앞바퀴 = 2, 뒷바퀴 = 2로 초기화




typedef 구조체

실제로 구조체를 선언하고 사용 할 때, 일일히 struct를 붙여주지 않는다.

ex) struct Tire 금호;

struct를 빼고 사용할 수 있도록, typedef를 이용한다.

  
struct Tire
{
   int 앞바퀴;
   int 뒷바퀴;
}

struct Tire 금호;
struct Tire 한국;
struct Tire 신발보다싸다;


이 모양에서

  
//typedef이용하여 쉽게 쓰기

typedef struct _Tire //형식상 구조체 이름은 _를 붙여준다. 꼭 붙여야 하는건 아님.
{
   int 앞바퀴;
   int 뒷바퀴;
   char 자동차[] = "제네시스";
} Tire;                   // typedef를 사용하여 구조체 별칭(태그)를 Tire로 정의

Tire 금호; // == struct Tire 금호;
Tire 한국;
Tire 신발보다 싸다;


typedef는 구조체 외에도 여러 곳에 이용할 수 있다.

ex)

  
typedef int MYNUM; //int를 MYNUM이라는 이름으로 사용
MYNUM age = 20; //int age = 20과 동일.




데이터 항목의 참조

구조체 내의 데이터에 접근하기 위해서는 연산자를 이용해야 한다.

  1. .(점) : 구조체 변수의 데이터 항목을 지정

  2. → (화살표) : 구조체형 포인터에서 포인터가 가리키는 구조체 변수의 데이터 항목을 지정.


1. 점 (.)

  
Tire 금호;
금호.앞바퀴 = 2;
금호.뒷바퀴 = 2;


2. 화살표(→)

구조체에 대한 포인터에서 사용한다. '*'로 대체하여 사용할 수도 있다.

  
Tire 금호;
Tire *금호송파점 = &금호; //구조체 포인터. 포인터 자체도 하나의 데이터타입이라는 것을 잊지 말자!
금호송파점 -> 앞바퀴 = 2;
(*금호송파점).뒷바퀴 = 2;
strcpy(금호송파점->자동차, "비틀"); //string은 직접 바꿀 수 없으므로, strcpy이용
//.이 *보다 우선순위가 높으므로, ()를 빼면 오류가 발생한다!




구조체 포인터

방법1:

  
struct 구조체이름 *포인터이름 = malloc(sizeof(struct 구조체이름));
struct Tire *금호송파점 = malloc(sizeof(struct Tire)); //포인터 선언+ 메모리 할당. 사용 후 free 해주어야 함!!!

방법2:

  
struct 구조체이름 *포인터이름 = &변수이름;

struct Tire 금호;
struct Tire *금호송파점;
*금호송파점 = &금호;



구조체 포인터를 쓰는 이유?

그런데 그냥 구조체로 .을 이용하여 직접 접근하면 되는데, 굳이 구조체 포인터를 써서 ->로 접근하는 이유는 무엇일까?

→ 보통 구조체는 멤버 변수가 여러 개 들어있어서 크기가 큰 편이다. 구조체를 호출할 때 오버헤드도 커진다. 그래서 구조체 변수를 일일이 선언해서 사용하는 것보다는 포인터에 메모리를 할당해서 사용하는 편이 효율적이다.




구조체의 연산

구조체에서 사용할 수 있는 연산

  1. 데이터 항목 참조 연산

  2. 구조체 변수 복사

  3. 구조체 변수의 주소 구하기 연산

  
typedef struct _Tire
{
   int 앞바퀴;
   int 뒷바퀴;
   char 자동차[] = "제네시스";
}

Tire 금호;
Tire 한국;
Tire 신발보다싸다;



1. 데이터 항목 참조 연산

: 점, 화살표를 이용해서 개별적으로 참조.

  
금호.앞바퀴 = 한국.뒷바퀴
strcpy(금호송파점->자동차, "비틀");


2.구조체 복사 연산

: 같은 구조체 간에는 내용을 한 번에 복사 가능.

  
금호 = 한국;
한국 = 신발보다싸다;


3.구조체 변수의 주소 구하기

: 구조체 배열 변수 이름에서 주소 구하기

  
struct Tire 금호, 한국;
struct Tire *ptr1, *ptr2;

ptr1 = &금호;




* C의 구조체와 JAVA의 클래스가 비슷한 것 같다.

  
// C에서의 구조체 사용

struct Tire
{
   int 앞바퀴;
   int 뒷바퀴;
}

struct Tire 금호;
struct Tire 한국;

금호.앞바퀴 = 2;

  
// JAVA에서의 클래스 사용
class Tire
{
   int 앞바퀴;
   int 뒷바퀴;
}

class Main
{
   Tire 금호 = new Tire();
   Tire 한국 = new Tire();
   금호.앞바퀴 = 2;
}