본문 바로가기
언어/C++

[C++ 기본 공부정리] 9. 구조체(struct)

by 민-Zero 2019. 12. 1.

공부 내용을 정리하는 목적 이므로 참고용으로만 읽어 주시기 바랍니다.

틀린 부분에 대한 지적은 감사합니다.

1. 구조체

어떤 객체를 표현할때 1가지의 변수 만으로는 부족한 경우가 있다. 예를 들어 학생이란 객체를 표현 하려한다면 이름, 나이, 학교, 학년, 학번, 전공 등등의 다양한 특징에 대한 변수가 필요하게 된다. 

학생이 1명뿐이라면 이렇게 6개변수를 일일이 선언하여 사용하여도 상관없지만 학생수가 많아 진다면 학생이 추가될때마다 일일이 새롭게 6개 변수를 추가해야 한다. 이런 점을 극복하기 위해 C++에서는 여러 개별 변수를 그룹화 하여 하나의 데이터 유형으로 생성할 수 있는 구조체를 제공한다. 배열이 같은 타입의 변수 집합이라고 한다면, 구조체는 다양한 타입의 변수 집합을 하나의 타입으로 나타낸 것 이라고 이해하면 된다. 이때 구조체를 구성하는 변수를 구조체의 멤버(member) 또는 멤버 변수(member variable)라고 하며 변수 뿐만 아니라 함수도 멤버 변수로 가질 수 있다.

즉, 구조체(structure)는 사용자가 하나 이상의 기본 타입을 가지고 새로운 자료형을 정의하는 사용자 정의 타입이다.

또한 구조체는 객체 지향 프로그래밍의 기본인 클래스(class)의 기본이 되므로 잘 기억 하자.

 

2. 선언 및 정의

문법)

struct 구조체명 {

     타입 멤버변수1;

     타입 멤버변수2;

     ....

};

구조체는 사용자가 새롭게 정의하는 자료형 이기 때문에 컴파일러에게 알려주지 않고 사용하게 되면 인식하지 못한다.따라서 사용하기 전에 미리 선언해야 한다. 구조체 또한 자료형이기 때문에 이 상태는 선언만 하였기 때문에 메모리가 따로 할당되지 않는다. 

Student구조체를 사용하려면 일반 변수처럼 Student 타입의 변수명을 정의 하게 되면 해당 변수에 대해 메모리가 할당되고 사용 할 수 있게 된다.

 

3. 멤버 접근 및 초기화

구조체의 멤버에 접근하기 위해서는 멤버 참조 연산자 ( . ) 을 이용한다.

문법) 구조체 변수명.멤버 변수명;

구조체 멤버 변수들도 일반 변수처럼 초기화를 하지 않으면 쓰레기값이 들어가 있기 때문에 초기화를 진행하여야 한다.

 

이처럼 일일이 진행할 경우 상당히 번거롭기 때문에 초기화 리스트를 통한 초기화 방법도 존재한다.

{}를 사용한 초기화 리스트를 통해 구조체의 전체 또는 일부를 초기화 할 수 있다.

문법) 구조체 변수명 = {멤버변수1, 멤버변수2, ...}; 

초기화 리스트를 이용하여 stu1은 모든 멤버 변수를 초기화 하였고 stu2는 일부만 초기화 하였다. 초기화 하지 않은 변수에는 default initialization 값 0 이 들어가 있는 것을 확인 할 수 있다.

 

또한 클래스(class)에서 자주 사용하게될 생성자(constructor)를 사용하는 방법도 있다.

생성자를 사용하게 되면 객체생성과 동시에 멤버 변수의 초기화를 진행할 수 있기 때문에 초기값을 지정해 줄때 사용하면 유용하다. 생성자에 관한 내용은 뒤에 자세히 정리하자.

 

4. 구조체 활용

1) 함수와 구조체

구조체는 구조체 멤버와 함께 함수에 전달 할 수 있으며 반환값으로도 사용 가능하다.

함수의 매개변수로 구조체를 넘겨주어 초기화 예제를 활용한 모습이다.만약 함수가 출력이 아닌 값의 변경일때 이 경우는 구조체의 원본 데이터를 복사하여 사용하여 원본 값의 변경이 없다. 원본 데이터를 바꾸고 싶다면 구조체 또한 메모리를 할당받기 때문에 포인터를 사용하여 변경 하면 된다.

 

구조체 타입으로 선언한 함수가 반환값을 구조체로 하여 다양한 변수를 한번에 넘겨 주는 것도 가능하다.

 

2) 구조체의 중첩

구조체는 다른 구조체를 멤버 변수로 사용 가능하다.

구조체 안의 구조체를 초기화 리스트를 통해 초기화 할 경우 {}를 2번 사용하면 되고 멤버 변수에 접근할 경우 (.)을 2번 사용 하면 된다.

 

3) 구조체 크기

구조체의 크기는 멤버 변수들의 크기를 합친것 으로 결정 되지만 항상 그렇지는 않다.

멤버변수의 크기를 전부 합치면 4+1+8 = 13 이지만 구조체의 크기는 16으로 나온다.

이유는 패딩(padding) 이라는 규칙 때문이다. 구조체를 메모리에 할당할 때 컴파일러는 프로그램의 속도 향상을 위해 패딩 규칙을 이용한다. 구조체는 다양한 크기의 타입을 멤버 변수로 가지고 있지만 컴파일러는 메모리의 접근을 쉽게 하려고 크기가 가장 큰 멤버 변수를 기준으로 모든 멤버 변수의 메모리 크기를 맞추어 버린다. 이것을 패딩이라고 하며, 이때 추가되는 바이트를 패딩 바이트(padding byte)라고 한다.

위의 예시를 그림으로 표현 하면

가장큰 double 8bytes가 존재 하므로 8bytes를 기준으로 크기가 결정된다.

맨 처음 int형 멤버 변수를 위해 8bytes가 할당되며, 할당되는 4bytes를 제외한 4bytes가 남게 되고 그다음 char형 멤버변수는 남은 4bytes보다 작으므로 그대로 남은 공간에 할당되어 3bytes가 남게된다. 마지막 남은 double형 멤버 변수는 8bytes로 남은 3bytes보다 크므로 새로 할당받게 된다. 따라서 예제의 구조체는 총 16bytes의 크기를 가지게 되고 남은 3bytes가 패딩 바이트가 된다.

댓글