IT이야기

헤더에 대한 "../include/header.h"와 같은 상대 경로의 이점

cyworld 2021. 10. 6. 22:39
반응형

헤더에 대한 "../include/header.h"와 같은 상대 경로의 이점은 무엇입니까?


include 지시문을 올바르게 사용하는 방법C++ #include 의미 체계 를 사용하는 방법에 대한 질문을 검토했으며 이 문제 해결하지도 않고 제목을 입력할 때 SO에서 제안한 다른 항목도 검토하지 않았습니다...

작성하면 어떤 이점이 있습니까?

#include "../include/someheader.h"
#include "../otherdir/another.h"

일반 파일 이름을 사용하는 것과 비교:

#include "someheader.h"
#include "another.h"

또는 ' ..'가 없는 상대 이름 :

#include "include/someheader.h"
#include "otherdir/another.h"

내가 보는 문제는 다음과 같습니다.

  • 헤더를 포함하는 소스 파일에 대해 걱정하지 않고 헤더를 이동할 수 없습니다.
  • 종속성 및 오류 보고서의 헤더 경로가 매우 길어질 수 있습니다. 나는 오늘 " ../dir1/include/../../include/../dir2/../include/header.h"로 하나를 가졌다 .

내가 볼 수있는 유일한 장점은 파일을 이동할 필요가 -I없지만 헤더를 찾기 위해 항상 ' ' 지시문을 사용하지 않고도 벗어날 수 있다는 것입니다. -디렉토리 등이 이점을 능가하는 것 같습니다.

그래서, 나는 이점을 간과하고 있습니까?


입력해 주셔서 감사합니다. 내가 간과하고 있는 ".."를 사용하는 표기법에는 큰 이점이 없다는 것이 합의라고 생각합니다. 일반적으로 나는 "somewhere/header.h" 표기법을 좋아합니다. 나는 새로운 프로젝트에서 그것을 사용합니다. 내가 작업하고 있는 것은 전혀 새롭지 않습니다.

문제 중 하나는 rspqr.h, rsabc.h, rsdef.h, 와 같은 접두사가 있는 다양한 헤더 집합이 있다는 것 rsxyz.h입니다. 이것들은 모두 rsmp디렉토리의 코드와 관련이 있지만 일부 헤더는 내부에 rsmp있고 다른 헤더는 내부 와 같은 하위 디렉토리가 없는 중앙 포함 디렉토리 rsmp에 있습니다. (그리고 코드의 다양한 다른 영역에 대해 반복합니다. 여러 위치에 헤더가 있으며 다른 코드 비트에서 무작위로 필요합니다.) 코드가 수년에 걸쳐 너무 복잡해지기 때문에 물건을 옮기는 것이 주요 문제입니다. 그리고 makefile은 어떤 -I옵션이 제공 되는지 일관성이 없습니다 . 대체로 이것은 수십 년 동안 그다지 호의적이지 않은 방치에 대한 슬픈 이야기입니다. 아무것도 파손하지 않고 모든 것을 수리하는 것은 길고 지루한 작업이 될 것입니다.


헤더 파일이 속한 네임스페이스 또는 모듈을 매우 명확하게 하는 경로 구문을 선호합니다.

#include "Physics/Solver.h"

모든 모듈이 헤더 파일에 이름을 접두사로 붙일 필요 없이 매우 자명합니다.

나는 ".." 구문을 거의 사용하지 않지만 대신 내 프로젝트가 올바른 기본 위치를 지정하도록 합니다.


문제 #include "../include/header.h"는 우연히 작동하는 경우가 많으며 관련이 없어 보이는 변경으로 인해 나중에 작동이 중지된다는 것입니다.

예를 들어 다음 소스 레이아웃을 고려하십시오.

./include/header.h
./lib/library.c
./lib/feature/feature.c

의 포함 경로로 컴파일러를 실행하고 있다고 가정해 보겠습니다 -I. -I./lib. 무슨 일이야?

  • ./lib/library.c할 수 있습니다 #include "../include/header.h".
  • ./lib/feature/feature.c#include "../include/header.h"의미가 없더라도 할 수 있습니다 . 이는 컴파일러가 #include현재 파일의 위치에 상대적인 지시문 을 시도하고 실패 하면 경로의 #include-I항목에 상대적인 지시문 을 시도하기 때문입니다 #include.

또한 나중에 경로 -I./lib에서 제거 #include하면 ./lib/feature/feature.c.

다음과 같은 것이 바람직하다고 생각합니다.

./projectname/include/header.h
./projectname/lib/library.c
./projectname/lib/feature/feature.c

나는 어떤이 아닌 다른 경로 항목을 포함 추가 할 것 -I., 그리고 모두 library.cfeature.c사용합니다 #include "projectname/include/header.h". "projectname"이 고유할 가능성이 있다고 가정하면 대부분의 상황에서 이름 충돌이나 모호성이 발생하지 않아야 합니다. 또한 VPATH절대적으로 필요한 경우 포함 경로 및/또는 make의 기능을 사용하여 여러 디렉터리에 걸쳐 프로젝트의 물리적 레이아웃을 분할할 수 있습니다(예를 들어 플랫폼별 자동 생성 코드를 수용하기 위해, 이것은 사용할 때 실제로 분해되는 것입니다 #include "../../somefile.h").


IANALL, 하지만 ..실제 C 또는 C++ 소스 파일 's 를 넣어야 한다고 생각하지 않습니다 . 왜냐하면 이식 가능하지 않고 표준이 지원하지 않기 때문입니다. 이것은 \Windows에서 를 사용하는 것과 유사합니다 . 컴파일러가 다른 방법으로 작동할 수 없는 경우에만 수행하십시오.


다음 #include ""과 같은 경우 하나 이상의 " ../"로 지시문 경로를 시작합니다 .

  • 포함 파일과의 배열이 고정된 파일을 포함하고 싶고
  • POSIX 시스템 또는 VC++로 구축 중이며
  • 어떤 파일이 포함될 것인지에 대한 모호함을 피하기를 원합니다.

코드 기반에 오류가 포함된 위치와 이로 인해 진단하기 어려운 오류가 발생하는 위치에 대한 예를 제공하는 것은 항상 쉽습니다. 그러나 프로젝트에 결함이 없더라도 절대 경로에 의존하여 서로 상대적인 위치에 있는 파일을 지정하면 제3자가 이를 악용할 수 있습니다.

예를 들어 다음 프로젝트 레이아웃을 고려하십시오.

./your_lib/include/foo/header1.h
./your_lib/include/bar/header2.h
./their_lib/include/bar/header2.h

어떻게해야 your_lib는 / / foo는 / header1.h 포함 포함 your_lib가 / 포함 / 바 / header2.h를 ? 두 가지 옵션을 고려해 보겠습니다.

  1. #include <bar/header2.h>

    your_lib/includetheir_lib/include 가 헤더 검색 경로로 인용 된다고 가정하면 (예: GCC -I또는 -isystem옵션 사용), 어떤 header2.h 가 선택 되는지 는 두 경로가 검색되는 순서에 민감합니다.

  2. #include "../bar/header2.h"

    컴파일러가 검색할 첫 번째 위치는 your_lib/include/foo/header1.h , 즉 your_lib/include/foo/ 입니다. 먼저 your_lib/include/foo/../bar/header2.h시도 하여 올바른 파일을 찾을 your_lib/include/bar/header2.h축소 합니다. 헤더 검색 경로는 전혀 사용되지 않으며 모호할 여지가 거의 없습니다.

주어진 이유로 이 경우 옵션 2)를 강력히 추천합니다.

다른 답변의 일부 주장에 대한 응답으로:

  • @andrew-grant 말한다 :

    ... 헤더 파일이 속한 네임스페이스 또는 모듈을 매우 명확하게 합니다.

    아마도. 그러나 상대 경로는 "이 동일한 모듈에서"로 해석될 수 있습니다. 다른 모듈에 같은 이름을 가진 여러 디렉토리가 있는 경우 명확성을 제공합니다.

  • @bk1e 말한다 :

    ... 종종 우연히 작동합니다 ...

    상대 경로는 프로젝트가 처음부터 중단되어 쉽게 고칠 수 있는 매우 드문 경우에만 우연히 작동한다고 주장하고 싶습니다. 컴파일러 오류를 일으키지 않고 이러한 이름 충돌을 경험하는 것은 거의 불가능해 보입니다. 일반적인 시나리오는 종속 프로젝트의 파일에 다른 헤더가 포함된 헤더 중 하나가 포함되어 있는 경우입니다. 테스트 스위트를 컴파일하면 해당 종속 프로젝트와 분리하여 컴파일할 때 "해당 파일이나 디렉터리가 없습니다" 오류가 발생해야 합니다.

  • @singlenegationelimination 라고

    ...이것은 이식성이 없으며 표준에서 지원하지 않습니다.

    The ISO C standard may not specify all the details of the systems under which a program is compiled or run. That does not mean that they are unsupported, merely that the standard doesn't over-specify the platforms on which C will run. (The distinction between how "" and <> are interpreted on common modern systems likely originates in the POSIX standard.)

  • @daniel-paull says

    the ".." assumes relative location and is fragile

    Fragile how? Presumably sensitive to the collocation of the two files. Thus ".." should only (and always) be used when the author of the including file controls their location.


Think of your source tree as a nested namespace and the include path is allowing you to pull directories into the root of this namespace. The question is then one of forming a logical namespace for your code base irrespective of how the code is organised on disk.

I would avoid paths like:

  • "include/foo/bar.h" — the "include" seems illogical and redundant
  • "../foo/bar.h" — the ".." assumes relative location and is fragile
  • "bar.h" — unless bar.h is in the current directory, this pollutes the global namespace and is asking for ambiguities.

Personally, I tend to add a path like the following to my projects include path — "..;../..;../../..;../../../..".

This allows you to apply a sort of hiding rule to your #includes and allows some freedom of moving headers without breaking other code. Of course this is at the expense of introducing a risk of binding to the wrong header file if you are not careful as non-fully qualified names may be (or become over time) ambiguous.

I tend to fully qualify #includes in public headers so any third parties consuming my code do not need to add the "..;../..;../../..;../../../.." to their project — it's just a convenience for my private code and build system.


Another issue on windows with relative paths is MAX_PATH. This will trigger compile issues when e.g. cross compiling for android and your path grows bigger than 260 in length.


Because then you place the file relative to the root of the project, and when you check it into source control and another developer checks it out to a different location on their local system things still work.

ReferenceURL : https://stackoverflow.com/questions/597318/what-are-the-benefits-of-a-relative-path-such-as-include-header-h-for-a-hea

반응형