본문 바로가기
프로그래밍/C & C++

[C] 구조체

by 불타는홍당무 2016. 3. 27.



01 구조체


구조체는 멤버(member)라고 하는 값들의 모임이여구조체의 멤버들은 대부분 서로 다른 타입으로 구성될 수 있는 통합 자료형이다.

 

*구조체 변수 선언 방법

 struct 구조체 자료형명(tag_name)

 {

           자료형 멤버1;

           자료형 멤버2;

           ..

           자료형 멤버 N;

 } 구조체 변수명;

 

struct 키워드는 컴파일러에게 구조체 자료형에 대한 선언임을 알리는 역할을 한다구조체 자료형명은 tag_name이라고도 하며 새로운 구조체 형에 대한 이름으로 사용자가 지정하는 이름이다. {  } 사이는 그 구조체를 구성하는 구성 요소즉 멤버들에 대한 선언 부분으로 멤버들의 선언은 일반 변수나 배열을 선언하듯이 자료형과 멤버명으로 선언한다구조체 자료형 선언이 끝나면 자료형을 이용할 구조체 변수명을 기술한다.

 


02 간단한 구조체의 개념

 

*학생들의 성적을 처리하기 위하여 구조체 자료형을 선언한 예

 struct score {          

           char name[20];

           int kor;

           int math;

           int eng;

           float avg;

 } st1 = {“까꿍이”, 93, 86, 89, 0.0};


구조체 변수의 각 멤버는 변수명/멤버명 형식으로 표현하면 된다이때 “ .”을 구조체 멤버 연산자라 하고구조체 안의 멤버는 직접 사용될 수 없으며,  “ .” 연산자를 사용하여 구조체 변수와 멤버를 연결하여 사용해야 한다멤버들에 대한 처리는 멤버들의 자료형에 맞추어 처리한다.

구조체 변수의 자료형의 크기를 알아야 하는 경우에는 sizeof() 함수를 사용한다.


 sizeof(struct score);        //구조체 자료형 이름으로 크기를 구할 때

 sizeof(st1);                   //구조체 변수명으로 크기를 구할 때

 

 #include <stdio.h>

 int main(void)

 {

          struct score{

                     char name[20];        // 학생 이름

                     int  kor;                 // 국어 시험 점수

          int  math;              // 수학 시험 점수

          int  eng;                // 영어 시험 점수

          float avg;               // 평균 점수

} st1 = {“까꿍이”, 93, 86, 89, 0.0};

 

           printf(“%d, %d \n”, sizeof(st1), sizeof(struct score));

           printf(“&st1 : %p, %p\n”, &st1, st1.name);

 

           st1.avg = {st1.kor + st1.math+st1.eng} / (float)3;

 

           // st1 구조체에 학생정보를 입력

           printf(“성명 ?”);

           gets(st1.name);

           printf(“국어 ? ”);

           scanf(“%d”, &st1.kor);

           printf(“수학 ? ”);

           scanf(“%d”, &st1.math);

           printf(“영어 ? ”);

           scanf(“%d”, &st1.eng);

 

           st1.avg = (st1.kor+st1.math+st1.eng} / (float)3;

           printf(“%s, %d, %d, %d, %.2f \n“, st1.name, st1.kor, st1.math, st1.eng, st1.avg);

           return 0;

 }

 36, 36

 &st1 : 7f7f0888, 7f7f0888

 까꿍이, 93, 86, 89, 89, 33

 성명 ? 진달래

 국어 ? 60

 수학 ? 80

 영어 ? 75

 진달래, 60, 80, 75, 71, 67




03 구조체의 선언과 정의

                                      

구조체 선언한다는 것은 메모리 할당이 이루어지지 않는 것을 말하며정의는 메모리 할당이 이루어지는 것을 말한다즉 구조체는 선언과 할당을 따로 할 수 있으며선언과 할당을 동시에 할 수도 있다.

 

*구조체 선언

 struct EMPLOYEE {         

   char name[20];

   char phone[15]

        int age

 }


구조체를 선언하며 score라는 구조체 자료형을 선언함이 때 메모리는 할당받지 못했으므로 score 구조체를 사용하기 위해서  

 EMPLOYEE  tag_name을 이용하여 구조체 변수를 정의하게 된다.


 struct EMPLOYEE st1, st2;            // s1 st2 2개의 구조체 변수 메모리에 할당


*구조체의 선언과 정의

 struct EMPLOYEE {

char name[20];

char phone[15]

int age

 }st1, st2 // 메모리 할당


구조체 선언과 동시에 st1, st2라는 구조체 변수로 메모리에 할당 받는다.

 

키워드 typedef는 이미 존재하는 자료형에 새로운 이름을 붙여 간단한 자료형 이름으로 사용하고자 할 때 이용된다구조체에서typedef를 많이 사용하고 있다.

 struct EMPLOYEE {        

                     char name[20];          

                     char phone[15];

                     intt age;            };

 typedef struct EMPLOYEE EMP; //새로운 자료형 명

 EMP st1 ; // 구조체 변수 메모리에 할당


이제 태그네임인 struct EMPLOYEE  대신에 EMP로 구조체 변수를 선언할 수 있다다음은 구조체 정의와 typedef 선언을 동시에 하는 문법이다.


 typedef struct EMPLOYEE {        

                      char name[20];    

                      char phone[15];

                      int age;            } EMP;

 EMP st1 ; // 구조체 변수 메모리에 할당

 



04 구조체 저장 공간의 할당


구조체는 실제 메모리상에서 어떻게 저장될까구조체 멤버들은 주어진 순서대로 메모리에 할당된다그러나 구조체가 경우에 따라서는 많은 빈 공간을 포함할 수 있다는 것을 알아야 하며멤버들 사이에 경계 정렬(boundary alignment)이 필요할 때 이러한 현상이 생기게 된다이를 얼라인먼트라 하며 cpu 사양에 따라 배치할 수 있는 주소에 한계가 있거나 효율적인 주소 사용을 위해 메모리의 경계를 적절히 조절함(속도향상을 위한 일)을 의미한다.

*구조체 멤버 선언의 위치는 가독성보다는 효율적인 메모리 사용(멤버 간 경계에서 메모리의 소모가 최소화되도록)에 우선순위를 둔다.


 #include <stdio.h>

 

 int main(void)

 {

    struct S {

       char a;

       int b;

       char c;

}st;

 

printf(“st1 : %d \n”, sizeof(st1));

return 0;

 }

 st1 : 12

  

a                                              b                                               c

 

 

 

 

 

 

 

 

 

 

 

 

그림 구조체 변수의 메모리 할당

 

정수 크기가 4바이트이고한 바이트가 4로 나누어지는 주소로 시작해야 하는 컴퓨터에서는 구조체의 첫 번째 멤버 a 4의 배수에 해당하는 주소에서 시작한다다음 멤버 b는 정수이므로 3개의 바이트를 건너뛰어 적정한 경계로 이동한다정수 다음에 마지막으로 c멤버가 저장되어야 하므로 12바이트를 할당하게 된다이 구조체는 12바이트의 메모리가 필요하지만 6바이트만을 사용하게 된다따라서 이 선언 구조는 좋은 방법이 아니다구조체의 경계 정렬에서 낭비되는 공간은 구조체 선언에서 멤버를 재배치하는 것으로 최소화할 수 있다.


 #include <stdio.h>


 int main(void)

 {

    struct S {

           int b;

           char a;

           char c;

}st;

 

printf(“st1 : %d \n”, sizeof(st1));

return 0;

 }

 st1 : 8


위와 같이 구조체의 첫 번째 멤버 b 4의 배수에 해당하는 주소에서 시작하였고, 2개의 문자는 서로 이웃하여 저장할 수 있기 때문에 낭비되는 공간은 그 구조체 다음에 두 바이트만 건너뛴다결과적으로 메모리를 4바이트 절약할 수 있다.

 

멤버들의 가독성을 위하여 연관성을 가진 구조체 멤버들을 함께 열거하여 메모리 낭비를 방치할지 아니면 메모리를 최소화하기 위해 세밀한 경계가 필요한 멤버들을 선언할 지는 개발자의 선택이나한 프로그램에서 수십개의 구조체를 포함하여 사용하는 경우경계 정렬로 인한 메모리 낭비가 가독성 문제보다 더 중요하게 된다이런 상황에서는 선언 부분의 주석을 추가하는 것이 읽어버린 가독성을 찾는데 도움이 될 수 있다.

 

 

05 구조체 배열


구조체 배열은 구조체 변수들을 여러 개의 연속된 공간에 모아 놓은 형태이므로 변수명 대신 배열명과 첨자를 이용한다는 점 이외에는 다를 것이 없다.

 

 struct score st[30];

 // st1[30] 구조체에 학생 정보를 입력한다면 다음과 같이 배열 첨자를 추가하면 된다.

 

 for(i=0; i<30; i++)

 {

           printf(“%d, 성명 ? ”, i+1);

           gets(st1[i].name);

           printf(“ 국어 ?”);

           scanf(“%d”, “&st1[i].kor);

 }



 


'프로그래밍 > C & C++' 카테고리의 다른 글

[C] 날짜/시간 처리 함수  (0) 2016.07.07
[C] 문자 처리 함수  (0) 2016.07.06
[C] 포인터  (0) 2016.03.31
[C] 문자열 처리함수  (0) 2016.03.22
[C] 헤더파일  (0) 2016.01.12