학교에서 시스템 프로그래밍을 C 언어로 공부하고 있습니다.
공부하면서 필요한 C 언어 개념들을 조금씩 정리해보려고 합니다.
글 내용이나 각각의 글들의 앞뒤가 없을 수 있으니.. 참고해주시고 궁금하신 점이나 잘못된 점들은 언제든지 피드백해주세요.
먼저 오늘은 C언어에서 사용되는 구조체의 개념에 대해서 공부해보겠습니다.
1. 구조체(struct)
먼저 아래 코드를 통해서 구조체의 기본적인 형태를 알아볼게요.
1 2 3 4 5 6 7 | struct (구조체 이름) { int var_1; float var_2; bool var_3; ... }; | cs |
1 2 3 4 | struct complex{ float real; float imag; }; | cs |
complex 라는 구조체는 float 자료형인 real 과 imag 변수를 내용으로 가지고 있습니다.
헌데 구조체를 만들 때 구조체 이름을 생략하는 경우가 있습니다. 먼저 예제를 확인하시죠.
1 2 3 4 | struct { float real; float imag; } var_complex; | cs |
위의 코드에서는 (구조체 이름) 이 생략되어 있습니다.
만약 구조체를 지속적으로 사용할 필요가 없고, 딱 한번만 선언해서 사용할때 위와 같은 형식으로 구조체를 만듭니다.
다시말해서 위의 코드의 구조체는 지속적으로 사용되는 것이 아니고 var_complex 라는 이름의 변수로
해당 구조체를 한번만 사용하는 것입니다.
그럼 이름이 있는 구조체의 경우에는 구조체를 어떻게 선언해서 사용할까요?
1 | struct complex var_complex; | cs |
위의 코드는 complex 라는 이름의 구조체를 var_complex 라는 이름의 변수로 선언한 것 입니다.
헌데 이런식으로라면 구조체를 선언할때마다 struct를 써야하는 번거로움이 생길 수 있습니다.
이를 해결하기 위해서 아래와 같이 typedef를 사용할 수 있습니다.
1 | typedef struct complex COMPLEX; | cs |
위의 코드가 말하는 것은, struct complex 라는 것을 COMPLEX 로 새로 정의할거야! 입니다.
즉, 해당 코드를 통해 다음부터 구조체를 선언할 때 아래와 같이 간단히 선언할 수 있습니다.
1 | COMPLEX var_complex; | cs |
우리가 흔히 int var; 처럼 int 형 변수 var를 선언하는 것과 같이 사용할 수 있는 것입니다.
또한, typedef를 이용하면 구조체를 만들 때 부터 구조체형의 이름을 지정할 수 있습니다.
아래 코드를 확인해볼까요?
1 2 3 4 5 | typedef struct complex { float real; // 멤버변수 float imag; }COMPLEX; COMPLEX var_complex; | cs |
위의 코드와 같이 구조체를 만들때 맨 앞에 typedef 를 이용하여 구조체 내용의 뒤에 구조체형의 이름을 지정해주면
이후 해당 구조체를 선언할때 struct ~ 를 생략하고 간편히 선언이 가능합니다.
구조체를 선언하고 사용하는 방법이 다양하게 있는데 헷갈리지 않도록 구분하여 이해하시길 바랍니다.
2. 구조체를 전달 받는 함수
구조체는 리턴이 될때 어떤식으로 리턴이 될까요?
C 언어에서 배열(array)는 해당 배열의 주소값으로 리턴이 됩니다.
하지만 구조체는 그렇지 않고 구조체의 값 자체가 리턴이 됩니다.
이럴때, 함수에 구조체를 그대로 전달한다면 무엇이 문제가 될까요?
만약 구조체의 값(내용)이 매우 크다면? 함수는 해당 값을 받고 처리하는 데 있어서 매우 비효율 적이 됩니다.
이에 따라서 구조체를 함수에 전달할 때에는 주로 '포인터'를 사용하게 됩니다.
아래 두 함수를 통해 차이점을 확인해 볼게요.
1 2 3 4 5 6 7 8 9 | // 구조체를 그대로 전달 받는 함수 void printComplex_1 (Complex c){ printf("real = %f, imag = %f\n", c.real, c.imag); } // 구조체 포인터를 전달 받는 함수 void printComplex_2 (Complex* ptr){ printf("real = %f, imag = %f\n", ptr->real, ptr->imag); } | cs |
먼저 1~4 번 라인의 함수는 구조체를 그대로 전달 받는 함수이며
6~9번 라인의 함수는 구조체를 포인터로써 전달 받아 사용하는 함수입니다.
위에서 말씀드렸듯이, 구조체를 그대로 전달 받는 함수는 매우 비효율적이기에 아래와 같은 포인터를 통해 구조체를 전달 받는 함수를 많이 사용합니다.