답변:
적절하게 사용하면 유용한 기술이 될 수 있습니다.
상당히 작은 공용 인터페이스와 재사용 불가능한 구현 코드가 많은 복잡하고 성능이 중요한 하위 시스템이 있다고 가정 해 보겠습니다. 코드는 수천 줄, 백 개 정도의 개인 기능 및 상당한 개인 데이터로 실행됩니다. 사소하지 않은 임베디드 시스템으로 작업하는 경우이 상황을 충분히 자주 처리 할 수 있습니다.
솔루션은 아마도 계층화되고 모듈화되고 분리 될 것이며 이러한 측면은 서브 시스템의 다른 부분을 다른 파일에 코딩하여 유용하게 표현하고 강화할 수 있습니다.
C를 사용하면 이렇게하면 많은 것을 잃을 수 있습니다. 거의 모든 툴체인은 단일 컴파일 단위에 대해 적절한 최적화를 제공하지만 extern으로 선언 된 모든 것에 대해 매우 비관적입니다.
모든 것을 하나의 C 소스 모듈에 넣으면-
성능 및 코드 크기 개선-많은 경우 함수 호출이 인라인됩니다. 인라인 없이도 컴파일러는 더 효율적인 코드를 생성 할 수 있습니다.
링크 레벨 데이터 및 기능 숨기기.
네임 스페이스 오염 및 그에 따른 결과 방지-덜 다루기 힘든 이름을 사용할 수 있습니다.
더 빠른 컴파일 및 연결.
그러나이 파일을 편집 할 때 거룩하지 않게 엉망이되고 함축 된 모듈성을 잃게됩니다. 이는 소스를 여러 파일로 분할하고이를 포함하여 단일 컴파일 단위를 생성함으로써 극복 할 수 있습니다.
그래도 제대로 관리하려면 몇 가지 규칙을 적용해야합니다. 이것들은 어느 정도 도구 체인에 따라 다르지만 몇 가지 일반적인 포인터는 다음과 같습니다.
공용 인터페이스를 별도의 헤더 파일에 넣으십시오. 어쨌든이 작업을 수행해야합니다.
모든 보조 .c 파일을 포함하는 하나의 기본 .c 파일이 있습니다. 여기에는 공용 인터페이스에 대한 코드도 포함될 수 있습니다.
컴파일러 가드를 사용하여 비공개 헤더와 소스 모듈이 외부 컴파일 단위에 포함되지 않도록합니다.
모든 개인 데이터 및 함수는 정적으로 선언되어야합니다.
.c 및 .h 파일 간의 개념적 구별을 유지하십시오. 이는 기존 규칙을 활용합니다. 차이점은 헤더에 많은 정적 선언이 있다는 것입니다.
도구 체인에서 그렇게하지 않는 이유가없는 경우 비공개 구현 파일의 이름을 .c 및 .h로 지정합니다. include 가드를 사용하면 코드가 생성되지 않고 새 이름이 도입되지 않습니다 (연결 중에 일부 빈 세그먼트가 생길 수 있습니다). 가장 큰 장점은 다른 도구 (예 : IDE)가 이러한 파일을 적절하게 처리한다는 것입니다.
괜찮아? 예, 컴파일됩니다
추천합니까? no-.c 파일은 .obj 파일로 컴파일됩니다. obj 파일은 컴파일 후 (링커에 의해) 실행 파일 (또는 라이브러리)로 함께 연결되므로 하나의 .c 파일을 다른 파일에 포함 할 필요가 없습니다. 대신 할 일은 다른 .c 파일에서 사용할 수있는 함수 / 변수를 나열하는 .h 파일을 만들고 .h 파일을 포함하는 것입니다.
나는 우리 팀이 .c 파일을 포함하기로 결정한 상황을 공유 할 것이라고 생각했습니다. 우리의 아키텍처는 주로 메시지 시스템을 통해 분리 된 모듈로 구성됩니다. 이러한 메시지 핸들러는 공용이며 많은 로컬 정적 작업자 함수를 호출하여 작업을 수행합니다. 이 개인 구현 코드를 실행하는 유일한 방법은 공개 메시지 인터페이스를 통해 간접적으로 수행하는 것이기 때문에 단위 테스트 케이스에 대한 커버리지를 얻으려고 할 때 문제가 발생했습니다. 일부 작업자 기능이 스택에 무릎 깊이 쌓여 있으면 적절한 적용 범위를 달성하는 데 악몽이되었습니다.
.c 파일을 포함하는 것은 우리가 테스트에서 흥미로운 기계의 톱니 바퀴에 접근 할 수있는 방법을 제공했습니다.
Linux에서 gcc 컴파일러를 사용하여 하나의 출력에 두 개의 c 파일을 연결할 수 있습니다. 하나는 'main.c'이고 다른 하나는 'support.c'인 두 개의 c 파일이 있다고 가정합니다. 따라서이 둘을 연결하는 명령은
gcc main.c support.c -o main.out
이 두 파일은 단일 출력에 링크됩니다. main.out 출력을 실행하려면 명령은 다음과 같습니다.
./main.out
support.c 파일에 선언 된 main.c에서 함수를 사용하는 경우 extern 스토리지 클래스를 사용하여 main.c에서도 선언해야합니다.
.C 또는 .CPP 파일을 다른 소스 파일에 올바르게 포함 할 수 있습니다. IDE에 따라 일반적으로 포함 할 소스 파일 속성을 확인하여 이중 연결을 방지 할 수 있습니다. 일반적으로 해당 속성을 마우스 오른쪽 단추로 클릭하고 속성을 클릭하고 빌드에서 컴파일 / 연결 / 제외 또는 다른 옵션을 선택 취소 / 선택합니다. 아마도. 또는 프로젝트 자체에 파일을 포함 할 수 없으므로 IDE는 파일이 존재하는지조차 모르고 컴파일을 시도하지 않습니다. 그리고 makefile을 사용하면 컴파일과 링크를 위해 파일을 넣지 않을 것입니다.
편집 : 미안하지만 다른 답변에 대한 답변 대신 답변을 만들었습니다.
C 언어는 그런 종류의 #include를 금지하지 않지만 결과 번역 단위는 여전히 유효한 C 여야합니다.
.prj 파일에 어떤 프로그램을 사용하고 있는지 모르겠습니다. "make"또는 Visual Studio 등을 사용하는 경우 독립적으로 컴파일 할 수없는 파일없이 컴파일되도록 파일 목록을 설정해야합니다.
C 파일을 다른 파일에 포함시키는 것은 합법적이지만,이 작업을 수행하는 이유와 달성하려는 목표를 정확히 알지 않는 한 권장하지 않습니다.
나는 당신이 당신의 질문 뒤에 커뮤니티가 당신의 목표를 달성하기위한 또 다른 더 적절한 방법을 찾을 수있는 이유를 여기에 게시 할 것이라고 거의 확신합니다 (컨텍스트가 주어진 해결책 일 가능성이 있기 때문에 "거의"에 유의하십시오. ).
그건 그렇고 나는 질문의 두 번째 부분을 놓쳤습니다. C 파일이 다른 파일에 포함되고 동시에 프로젝트에 포함 된 경우 개체를 연결하는 이유가 중복 기호 문제로 끝날 것입니다. 즉, 동일한 기능이 두 번 정의됩니다 (모두 정적이 아닌 경우).