0. C언어를 배우며

지난 인턴 기간 동안 저는 자료구조와 알고리즘에 대해서 어렴풋이 알고는 있었지만, 실제로 다른 문제에 부딪혔을 때, 어떻게 해결하면 좋을까에 대해서 막막한 상태였습니다. 이때, 자료 구조와 알고리즘이 큰 역할을 하면서 문제를 해결한다는 것을 알게 되었고, 지난 3월부터 계속해서 자료구조와 알고리즘에 대해서 복습하고 코드를 짜보며 복습 중입니다. 기존에 사용하던 언어인 Python으로도 얼마든지 공부를 진행할 수 있을 수도 있지만, Python의 경우에는 High Level의 언어 중에서도 많이 High Level이기 때문에 쉽게 쉽게 코드를 짤 수 있는 장점이 존재하지만, 자료구조를 공부할 때에는 포인터를 쓸 수 있는 C&C++이 더 좋다고 생각을 해서 옛날에 공부하였던 언어들을 다시 꺼내게 되었습니다. 그렇게 Python의 생산성에 감탄을 표하게 되고

 

C언어및 C++를 공부할 때 필요한 Visual studio code의 세팅의 경우에는 구글에 검색해보면 많은 양의 정보가 나오니 따로 적지는 않겠습니다. 

I. 문제 봉착

이렇게 C언어를 한 번 복습하고, 본격적으로 자료구조를 공부하려던 저에게 다음과 같은 문제가 생기게 되었습니다.

 

undefined reference to 

바로 다음과 같이 여러 변수들이나 함수들이 undefined reference to로 나온다는 점이었습니다. 기존의 C언어 프로그래밍 오류는 제가 포인터를 잘못 설정하거나 변수를 잘못 적어서 일어나는 경우가 많았는데, 이와 같은 경우는 말 그대로 referenence의 각각 함수와 변수들이 잘못 설정이 되었다고 나오게 되었습니다. 하지만 저는 분명 header파일과 c파일로 각각의 함수들을 지정해주고, 정의를 하며 마지막에 mainfuncition이 있는 곳에서 실행하도록 만들어서 겹치지도 않는데 다음과 같은 문제가 발생하였습니다. 실제로 설루션을 다시 가져와도 같은 반응입니다. (본격 공부하는데 환경 때문에 미치는 케이스)

 

어떤 점이 문제일까요?

 

II. C언어의 특수성:  헤더파일과 c파일

 

파일 리스트

제가 사용한 파일의 경우 이렇게 세 가지로 나뉘게 됩니다. 그중 linkedlist의 경우 헤더 파일과 c 파일이 존재를 합니다. 많은 분들이 인터넷에 설명을 해주셨듯이 헤더 파일은 메뉴판, c파일은 본격적으로 조리하는 단계라고 보시면 됩니다. 이러한 점은 python에서도 코드가 너무 길어질 경우에 따로 py파일로 분리하여서 import - 혹은 from ~ import - 이런 식으로 각각의 함수들이나 파일 통째로 main 프로그램에서 가져 쓸 수 있게 하여서, 함수를 한 파일이 아닌 다른 파일에서도 사용이 가능하게 만들 뿐만이 아니라 코드를 분리시켜서 유지 및 보수, 수정이 더욱 쉽게 만들 수 있다는 장점이 있습니다. C언어에서는 이러한 외부에서 가져오는 c파일을 헤더 파일과 c파일로 분리하여서 사용하게 된다고 이해하시면 될 것 같습니다. 하지만 이러한 점 때문에 문제가 생기게 됩니다.

 

undefined reference to의 의미는 분명 메뉴판에는 A라는 함수가 있는데, 정작 A를 어떻게 조리할까에 대한 내용이 없을 때 발생하게 되는 것 입니다. 하지만 이렇게 반문할 수가 있을 것 같습니다.

"어? 나는 linkedlist.c라는 파일에서 그 함수를 정의를 해줬는데?"

네 맞습니다. 하지만 visuasl studio code나 gcc에서 이 순서를 반대로 컴파일을 하게 된다면 인식이 되지 않는게 당연합니다. 마치 햄버거를 조립하려고 하는데, 패티가 아직 굽히지 않는 상태와 같다고 할까요? (비유 참...)

 

III. 해결 방법

III-1. 헤더파일이고 뭐고 제거

 

결국에는 헤더파일, c파일, 메인 파일은 하나의 프로그램 코드를 각각 편의성에 맞게 분리한 것에 불과합니다. 때문에 분리하는 것을 하나로 합치면 코드가 성공적으로 돌아가긴 합니다. 파일이 몇 개 없을 때는 이 점이 제일 간편하는 방법인 것 같습니다. 하지만 이러한 점의 문제점도 존재를 하는데요.

먼저, 헤더 파일이나, c파일이 여러 파일을 넘어 갈 경우에는 굉장히 번거로운 사태가 발생을 합니다. 하나의 메인 함수에 다 붙여한다니.. 순서를 고려하면서 말이죠. 또한, 파일들과의 순서 말고도 안에서 #define이나 #include를 위로 올려 보내는 과정, 또 각각의 함수가 어떤 의존성을 가지는지 모두 파악을 하고 오려 붙여 야한다는 점이 있습니다.

두 번째론, 헤더파일과 c파일을 분리시킨 이유가 명백히 있을 시에는 이를 반감시킬 수 있습니다. 앞서 말한 듯 분리시키는 경우에는 다른 c 프로그램에서도 사용할 수도 있다는 점이 있습니다. 하지만 이렇게 하나의 파일에 몰아놓고 집중을 하게 되면, 이 파일에 의존성을 가진 프로그램들이 작동을 하지 않을 가능성이 높습니다. 

이러한 점 때문에 이론 공부에 사용하는 비교적 간단한 파일의 경우에는 추천을 드리지만, 완벽한 방법은 아닙니다.

 

III.-2 Terminal에서 gcc를 이용한 

많은 Visual studio code에서 환경설정을 해주는 것은 결국에는 gcc를 실행하는 것을 자동화시켜준다는 점에 불구합니다. 이 때문에 터미널에서 저희가 직접 gcc를 실행하는데, 우선순위를 정해서 순서대로 컴파일을 하면 문제가 해결이 됩니다.

터미널에 입력할 저희의 명령어는 다음과 같습니다.

 

gcc -o (컴파일로 생성할 이름) (main 함수가 있는 c파일) (연결된 c파일)

이 때, 컴파일로 생성할 이름과 main 함수가 있는 c파일의 이름이 일치하면 좋습니다.

연결된 c파일의 경우에는 헤더 파일과 보통 같은 이름으로 정해주는 프로그램을 의미합니다. 의존성이 심한 즉 많은 함수나 변수들을 다른 c파일과 헤더 파일에서 정의한 것을 가져다 쓰는 파일을 가장 앞으로 보내는 것이 좋습니다. 보통은 main 함수가 있는 파일이 가장 많이 함수들과 변수들을 다른 헤더 파일들과 c파일에서 가져다 사용하기 때문에 컴파일로 생성할 이름 뒤에 main 함수가 있는 c파일의 제목을 넣어주는 것이 좋습니다.

 

저의 경우에는

 

다음과 같이 넣게 되었습니다. 컴파일로 생성할 이름과 main 함수가 있는 c파일을 이렇게 같게 넣어주는 이유는 많은 분들이 참고하시는 VS code의 설정이 main 함수가 들어 있는 c 파일과 같은 이름을 가진 컴파일된 프로그램을 찾아서 실행하고 있기 때문입니다. 다르게 설정하면 아무리 실행을 해도 실행 파일은 있는데 실행을 하지 않을 수도 있습니다. 하지만 터미널을 이용하여 실행파일도 내가 직접 실행을 하겠다는 분들은 원하시는 이름으로 적어도 될 것 같습니다.

 

위에서 나온데로 터미널에 명령을 입력하게 되면

 

이렇게 컴파일된 프로그램이 생기는 것을 알 수가 있습니다. 이때, 컴파일해서 만들 프로그램 이름을 따로 지정해주지 않으면 가장 앞 파일이 사라지는 것을 목격할 수가 있으니 주의를 해주시길 바랍니다.

 

이렇게 컴파일을 한 프로그램은 실행을 하여 결과를 확인할 수가 있게 됩니다.

 

원 코드에서 문자열이 깨져서 다음과 같이 나오긴 하지만, 실행은 됩니다!

 

 

IV. 마치며

C언어는 공부할 때마다 정말 포인터 때문에 미칠 거 같고 변수도 일일히 형태를 다 지정을 해주어야 해서 솔직히 쉽다고도, 또 생산성이 높다고도 이야기를 못하겠습니다. 오늘 다룬 주제와 같이 컴파일과 실행의 개념이 또 존재를 하기 때문에 진입장벽이 낮다고도 이야기를 못할 것 같습니다. 하지만, 컴퓨터 이론 공부를 할 때, 가장 깊게 이해하는데 도움을 주고, 파이썬이나 다른 프로그래밍 언어에서 배울 수 없던 점들을 C 언어에서 일일이 수동으로 할당해가면서 할 경우에는 가장 아래의 단계에서 문제를 이해하고 해결하는데 도움을 줄 수 있는 언어인 것 같습니다. 비록 인제 C언어를 사용해 다른 공부를 시작하였지만, 앞으로도 계속 이런 점들을 정리해나가면서 C언어 고수가 되어봐야겠습니다.

 

+ Recent posts