c++ - make - include custom header file c




#include<filename>과#include "filename"의 차이점은 무엇입니까? (20)

C 및 C ++ 프로그래밍 언어에서 다음과 같이 꺾쇠 괄호를 사용하는 것과 include 문에서 따옴표를 사용하는 것의 차이점은 무엇입니까?

  1. #include <filename>
  2. #include "filename"

"<filename>"은 표준 C 라이브러리 위치에서 검색합니다.

"filename"은 현재 디렉토리에서도 검색합니다.

표준 C 라이브러리의 경우 <...>를 사용하고 현재 디렉토리에 작성하고있는 라이브러리의 경우 "..."를 사용하는 것이 이상적입니다.


#include <filename>

C / C ++ 시스템 또는 컴파일러 라이브러리의 헤더 파일을 사용하려는 경우에 사용됩니다. 이러한 라이브러리는 stdio.h, string.h, math.h 등이 될 수 있습니다.

#include "path-to-file/filename"

프로젝트 폴더 또는 다른 곳에있는 사용자 정의 헤더 파일을 사용하고자 할 때 사용됩니다.

전 처리기 및 헤더에 대한 자세한 정보. C - 전처리기를 읽습니다 .


#include <filename>을 사용하면 전처리 기는 C \ C ++ 헤더 파일 (stdio.h \ cstdio, string, vector 등)의 디렉토리에서 파일을 찾고 있습니다. 하지만, #include "filename"을 사용할 때 : 현재 프로세서는 현재 디렉토리에서 파일을 찾고, 그렇지 않다면 C \ C ++ 헤더 파일의 디렉토리에서 찾고 있습니다.


<와> 사이의 문자 시퀀스는 머리글을 고유하게 참조하며 반드시 파일 일 필요는 없습니다. 구현시 문자 시퀀스를 원하는만큼 자유롭게 사용할 수 있습니다. (대부분의 경우 파일 이름으로 처리하고 포함 경로 에서 검색을 수행합니다. 다른 게시물 상태입니다.)

#include "file" 형식이 사용되면 구현시 먼저 지원되는 경우 지정된 이름의 파일을 찾습니다. 지원되지 않거나 지원되지 않으면 검색이 실패하면 다른 ( #include <file> ) 형식이 사용 된 것처럼 구현이 작동합니다.

또한 세 번째 형식이 존재하며 #include 지시문이 위 양식 중 하나와 일치하지 않을 때 사용됩니다. 이 형식에서는 매크로 확장과 같은 일부 기본 사전 처리가 #include 지시문의 "피연산자"에서 수행되며 그 결과는 다른 두 형식 중 하나와 일치해야합니다.


그렇습니다:

"mypath/myfile" is short for ./mypath/myfile

. #include 가 들어있는 파일의 디렉토리 및 / 또는 컴파일러의 현재 작업 디렉토리 및 / 또는 default_include_paths

<mypath/myfile> is short for <defaultincludepaths>/mypath/myfile

./<default_include_paths> 에 있으면 차이가 없습니다.

mypath/myfile 이 다른 include 디렉토리에 있으면 동작은 정의되지 않습니다.


꺽쇠 괄호가있는 #include는 포함될 파일에 대한 "구현 위치에 따른 장소 목록"( "시스템 헤더"를 말하는 매우 복잡한 방법)을 검색합니다.

인용 부호가있는 #include는 단지 파일을 검색 할 것이다 (그리고 "구현 - 의존적 인 방식으로", bleh). 즉, 일반적인 영어로, 당신이 그것에 던져 넣을 경로 / 파일 이름을 적용하려고 시도하고 그렇지 않으면 시스템 경로를 prepend하지 않거나 그렇지 않으면 그것을 변경하지 않습니다 것을 의미합니다.

또한 #include ""가 실패하면 표준에 따라 #include <>로 다시 읽습니다.

g++ 는 (컴파일러 관련) 설명을 가지고 있지만 ISO 표준에 대한 변호사 스타일의 이야기보다 이해하기 쉽지만 표준이 아닌 gcc와 관련이 있습니다.


실제로 차이점은 전 처리기가 포함 된 파일을 검색하는 위치에 있습니다.

#include <filename> 대해 전 처리기는 일반적으로 컴파일러 / IDE에 의해 사전 지정된 검색 디렉토리에서 구현 종속적 인 방식으로 검색합니다. 이 방법은 일반적으로 표준 라이브러리 헤더 파일을 포함하는 데 사용됩니다.

#include "filename" 경우 전 처리기는 지시문이 들어있는 파일과 동일한 디렉토리에서 먼저 검색 한 다음 #include <filename> 양식에 사용 된 검색 경로를 따릅니다. 이 메소드는 일반적으로 프로그래머가 정의한 헤더 파일을 포함하는 데 사용됩니다.

검색 경로 에 대한 GCC 문서 에서 더 자세한 설명을 볼 수 있습니다.


알아야 할 유일한 방법은 구현 문서를 읽는 것입니다.

C 표준 , 6.10.2 절에서 2 단락부터 4 단락은 다음과 같이 설명합니다.

  • 양식의 전처리 지시문

    #include <h-char-sequence> new-line
    

    <> 구분 기호 사이에 지정된 순서로 고유하게 식별 된 헤더에 대해 구현 정의 된 장소의 시퀀스를 검색하고 그 지시문을 헤더의 전체 내용으로 대체합니다. 장소가 지정되는 방법 또는 식별 된 헤더가 구현 정의되는 방법.

  • 양식의 전처리 지시문

    #include "q-char-sequence" new-line
    

    " 구분 기호 (delimiter) " 사이의 지정된 순서로 식별되는 소스 파일의 전체 내용에 의해 해당 지정 문을 대체합니다. 명명 된 소스 파일은 구현 정의 방식으로 검색됩니다.이 검색이 지원되지 않거나 검색에 실패하면 , 지시문은 읽은 것처럼 다시 처리됩니다

    #include <h-char-sequence> new-line
    

    원래의 지시문에 포함 된 동일한 문자 (포함 된 경우)를 포함합니다.

  • 양식의 전처리 지시문

    #include pp-tokens new-line
    

    (이전 두 양식 중 하나와 일치하지 않음)이 허용됩니다. 지시문에 include 전 처리 토큰은 일반 텍스트 에서처럼 처리됩니다. (현재 매크로 이름으로 정의 된 각 식별자는 전처리 토큰의 교체 목록으로 대체됩니다.) 모든 대체 후 결과로 나오는 지시문은 이전 두 형식 중 하나와 일치해야합니다. <> 전처리 토큰 쌍 또는 " 문자 쌍 " 사이의 사전 처리 토큰 시퀀스가 ​​단일 헤더 이름 전처리 토큰으로 결합되는 방법은 구현에 따라 정의됩니다.

정의 :

  • h-char : 개행 문자와 > 문자를 제외한 소스 문자 세트의 모든 멤버.

  • q-char : 개행 문자를 제외한 소스 문자 세트의 모든 멤버와 "


여기서 좋은 대답은 C 표준을 언급하지만 POSIX 표준, 특히 c99 (예 : C 컴파일러) 명령의 특정 동작을 잊어 버린 것입니다.

The Open Group Base Specifications Issue 7 에 따르면,

-I 디렉토리

이름이 절대 경로 이름이 아닌 헤더를 검색하는 알고리즘을 변경하여 일반적인 경로를 찾기 전에 디렉토리 경로 이름에 지정된 디렉토리에서 찾습니다. 따라서 이름을 큰 따옴표 ( "")로 묶은 헤더는 먼저 #include 행을 포함하는 파일의 디렉토리에서 찾은 다음 -I 옵션에서 이름 지정된 디렉토리에서 검색하고 일반적인 위치에서 마지막으로 찾습니다. 이름이 꺽쇠 괄호 ( "<>")로 묶인 헤더의 경우 헤더는 -I 옵션에서 이름이 지정된 디렉토리에서 검색된 다음 일반 위치에서 검색됩니다. -I 옵션으로 명명 된 디렉토리는 지정된 순서대로 검색되어야한다. 구현은 단일 c99 명령 호출에서이 옵션의 10 개 이상의 인스턴스를 지원해야합니다.

따라서 POSIX 호환 환경에서 POSIX 호환 C 컴파일러를 사용하면 #include "file.h"./file.h 먼저 검색 할 가능성이 높습니다 . #include <file.h>/usr/include/file.h 먼저 검색하는 동안 #include 문이있는 파일이있는 디렉토리입니다. 여기서 /usr/include 는 시스템에서 정의 된 일반적인 위치 입니다. 헤더 (POSIX에 정의되지 않은 것 같습니다).


위대한 답변, 특히 주셔서 감사합니다. Adam Stelmaszczyk 및 piCookie, aib.

많은 프로그래머와 마찬가지로 필자는 응용 프로그램 특정 파일에 "myApp.hpp" 양식을 사용하는 비공식적 인 규약과 라이브러리 및 컴파일러 시스템 파일에 대한 <libHeader.hpp> 양식 (예 : /IINCLUDE 환경 변수에 지정된 파일)을 사용했습니다. 그것이 수년 동안 표준이라고 생각했습니다.

그러나 C 표준에 따르면 검색 순서는 구현에 따라 다르므로 이식성이 복잡해질 수 있습니다. 설상가상으로, 잼 (jam)을 사용합니다. 잼 (jam)은 포함 파일의 위치를 ​​자동으로 찾아냅니다. 포함 파일에 상대 경로 또는 절대 경로를 사용할 수 있습니다. 즉

#include "../../MyProgDir/SourceDir1/someFile.hpp"

이전 버전의 MSVS에서는 이중 백 슬래시 (\\)가 필요했지만 지금은 필요하지 않습니다. 그것이 언제 바뀌 었는지 나는 모른다. 'nix와의 호환성을 위해 슬래시를 사용하십시오 (Windows에서는이를 사용할 수 있습니다).

정말 걱정된다면, 소스 코드와 같은 디렉토리에있는 include 파일에 "./myHeader.h" 를 사용하십시오. (현재의 매우 큰 프로젝트에는 몇 가지 중복 된 파일 이름이 포함되어 있습니다. 실제로 구성 관리 문제입니다. ).

다음은 사용자의 편의를 위해 여기에 복사 된 MSDN 설명 입니다.)

인용 형식

전처리 기는 다음 순서로 포함 파일을 검색합니다.

  1. #include 문을 포함하는 파일과 동일한 디렉토리에 있습니다.
  2. 현재 열려있는 포함 파일의 디렉토리에서, 다음과 같은 역순으로
    그들은 열렸다. 상위 포함 파일의 디렉토리에서 검색이 시작되고
    모든 조부모 포함 파일의 디렉토리를 통해 위로 계속됩니다.
  3. /I 컴파일러 옵션으로 지정된 경로를 따라 이동합니다.
  4. INCLUDE 환경 변수로 지정된 경로를 따라 이동합니다.

앵글 브래킷 형태

전처리 기는 다음 순서로 포함 파일을 검색합니다.

  1. /I 컴파일러 옵션으로 지정된 경로를 따라 이동합니다.
  2. 컴파일 할 때 INCLUDE 환경 변수에 의해 지정된 경로를 따라 명령 행에서 수행됩니다.

표준에 의해 - 네, 그들은 다릅니다 :

  • 양식의 전처리 지시문

    #include <h-char-sequence> new-line
    

    <> 구분 기호 사이에 지정된 순서로 고유하게 식별 된 헤더에 대해 구현 정의 된 장소의 시퀀스를 검색하고 그 지시문을 헤더의 전체 내용으로 대체합니다. 장소가 지정되는 방법 또는 식별 된 헤더가 구현 정의되는 방법.

  • 양식의 전처리 지시문

    #include "q-char-sequence" new-line
    

    " 구분 기호 (delimiter) " 사이의 지정된 순서로 식별되는 소스 파일의 전체 내용에 의해 해당 지정 문을 대체합니다. 명명 된 소스 파일은 구현 정의 방식으로 검색됩니다.이 검색이 지원되지 않거나 검색에 실패하면 , 지시문은 읽은 것처럼 다시 처리됩니다

    #include <h-char-sequence> new-line
    

    원래의 지시문에 포함 된 동일한 문자 (포함 된 경우)를 포함합니다.

  • 양식의 전처리 지시문

    #include pp-tokens new-line
    

    (이전 두 양식 중 하나와 일치하지 않음)이 허용됩니다. 지시문에 include 전 처리 토큰은 일반 텍스트 에서처럼 처리됩니다. (현재 매크로 이름으로 정의 된 각 식별자는 전처리 토큰의 교체 목록으로 대체됩니다.) 모든 대체 후 결과로 나오는 지시문은 이전 두 형식 중 하나와 일치해야합니다. <> 전처리 토큰 쌍 또는 " 문자 쌍 " 사이의 사전 처리 토큰 시퀀스가 ​​단일 헤더 이름 전처리 토큰으로 결합되는 방법은 구현에 따라 정의됩니다.

정의 :

  • h-char : 개행 문자와 > 문자를 제외한 소스 문자 세트의 모든 멤버.

  • q-char : 개행 문자를 제외한 소스 문자 세트의 모든 멤버와 "

이 표준은 구현이 정의한 방식 사이의 관계를 말하지 않는다는 점에 유의하십시오. 첫 번째 형식은 한 구현 정의 방식으로 검색하고 다른 형식은 구현 정의 방식으로 검색합니다. 또한이 표준은 특정 포함 파일이 있어야한다고 지정합니다 (예 : <stdio.h> ).

공식적으로 컴파일러의 매뉴얼을 읽어야하지만, 보통 (전통적으로) #include "..." 형식은 #include 가 먼저 발견 된 파일의 디렉토리를 검색 한 다음 #include <...> 양식 검색 (포함 경로, 예 : 시스템 헤더)을 포함합니다.


GCC 문서는 이 둘의 차이에 대해 다음과 같이 말합니다 .

사용자 및 시스템 헤더 파일은 전처리 지시문 '#include' 사용하여 포함됩니다. 그것은 두 가지 변종이 있습니다 :

#include <file>

이 변형은 시스템 헤더 파일에 사용됩니다. 시스템 디렉토리의 표준 목록에서 file이라는 파일을 검색합니다. -I 옵션을 사용하여이 목록에 디렉토리를 추가 할 수 있습니다 ( Invocation 참조).

#include "file"

이 변형은 사용자 프로그램의 헤더 파일에 사용됩니다. 현재 파일을 포함하는 디렉토리에서 file이라는 파일을 찾은 다음 견적 디렉토리에서 <file> 사용 된 동일한 디렉토리를 검색 <file> . -iquote 옵션을 사용하여 디렉토리를 따옴표 디렉토리 목록 앞에 추가 할 수 있습니다. 인용 부호 또는 꺽쇠 괄호로 구분 된 '#include' 인수는 주석이 인식되지 않고 매크로 이름이 확장되지 않는다는 점에서 문자열 상수와 같이 동작합니다. 따라서 #include <x/*y>x/*y 라는 이름의 시스템 헤더 파일을 포함하도록 지정합니다.

그러나 파일에서 백 슬래시가 발생하면 이스케이프 문자가 아닌 일반 텍스트 문자로 간주됩니다. C에서 문자열 상수에 적합한 문자 이스케이프 시퀀스는 처리되지 않습니다. 따라서 #include "x\n\\y" 는 세 개의 백 슬래시가 포함 된 파일 이름을 지정합니다. (어떤 시스템에서는 '\'를 경로 이름 분리 자로 해석하며, 모두 '/' 와 같은 방식으로 해석합니다. '/' 만 사용하는 것이 가장 좋습니다.)

파일 이름 다음에 행에 아무 것도 (주석 제외) 있으면 오류입니다.


#include <file.h> 는 "includes"디렉토리에서 헤더를 검색하도록 컴파일러에 지시합니다. 예를 들어 MinGW의 경우 컴파일러는 C : \ MinGW \ include \ 또는 컴파일러가 설치된 모든 위치에서 file.h 를 검색합니다.

#include "file" 은 현재 디렉토리 (즉, 소스 파일이 상주하는 디렉토리)에서 파일을 검색하도록 컴파일러에 지시 file .

GCC에 -I 플래그를 사용하여 각괄호가있는 포함을 발견하면 -I 뒤에 디렉토리의 헤더도 검색해야 함을 알릴 수 있습니다. GCC는 플래그 includes 디렉토리를 includes 디렉토리 인 것처럼 취급합니다.

예를 들어, 자신의 디렉토리에 myheader.h 라는 파일이 있다면 -I . 플래그와 함께 GCC를 호출하면 #include <myheader.h> 라고 말할 수 있습니다 -I . (현재 디렉토리에서 include를 검색해야 함을 나타냄).

-I 플래그가 없으면 #include "myheader.h" 를 사용하여 파일을 포함 시키거나 myheader.h 를 컴파일의 include 디렉토리로 이동해야합니다.


#include <filename>

C ++ 라이브러리에서 해당 파일을 찾습니다. C ++ 라이브러리 폴더에 hello.h라는 파일이 있다면 #include <hello.h>로드 할 것입니다.

그러나,

#include "filename"

소스 파일이있는 동일한 디렉토리에서 파일을 찾습니다.

게다가,

#include "path_to_file/filename"

입력 한 디렉토리에서 파일을 찾습니다 path_to_file.


<file> include는 전 처리기에게 -I 디렉토리와 미리 정의 된 디렉토리를 검색 한 다음 .c 파일의 디렉토리에서 검색하도록 지시합니다. "file" include는 소스 파일의 디렉토리를 먼저 검색 한 다음 -I 로 돌아가서 미리 정의하도록 전 처리기에 지시합니다. 모든 목적지는 어쨌든 검색되지만 검색 순서 만 다릅니다.

2011 표준에서는 "16.2 소스 파일 포함"의 포함 파일에 대해 주로 설명합니다.

2 양식의 사전 처리 지시문

# include <h-char-sequence> new-line

<와> 구분 기호 사이에 지정된 순서로 고유하게 식별 된 헤더에 대해 구현 정의 된 장소의 시퀀스를 검색하고 그 지시문을 헤더의 전체 내용으로 대체합니다. 장소가 지정되는 방법 또는 식별 된 헤더가 구현 정의되는 방법.

3 양식의 사전 처리 지시문

# include "q-char-sequence" new-line

"구분 기호 (delimiter)"사이의 지정된 순서로 식별되는 소스 파일의 전체 내용에 의해 해당 지정 문을 대체합니다. 명명 된 소스 파일은 구현 정의 방식으로 검색됩니다.이 검색이 지원되지 않거나 검색에 실패하면 , 지시문은 읽은 것처럼 다시 처리됩니다

# include <h-char-sequence> new-line

원래의 지시문에 포함 된 동일한 문자 (포함 된 경우)를 포함합니다.

파일이 없으면 "xxx" 양식이 <xxx> 양식으로 변환됩니다. 나머지는 구현에 따라 정의됩니다.


다음 두 가지 방법으로 #include 문을 작성할 수 있습니다.

#include"filename"
#include<filename>

각 양식의 의미는 다음과 같습니다.

#include"mylib.h"

이 명령은 mylib.h현재 디렉토리 의 파일 뿐만 아니라 설정된 포함 된 검색 경로에 언급 된 지정된 디렉토리 목록을 찾습니다.

#include<mylib.h>

이 명령은 mylib.h지정된 디렉토리 목록에서만 파일 을 찾습니다 .

포함 검색 경로는 포함되는 파일을 검색 할 디렉토리 목록 일뿐입니다. 다른 C 컴파일러를 사용하면 검색 경로를 다른 방식으로 설정할 수 있습니다.


검색 헤더 파일의 순서가 다릅니다. <XXX.h>는 표준 헤더를 먼저 검색하는 반면 "XXX.h"는 작업 영역의 헤더 파일을 먼저 검색하는 것을 선호합니다.


현재 구성에 따라 gcc를 사용하여 시스템에서 검색 순서를 보려면 다음 명령을 실행할 수 있습니다. 이 명령에 대한 자세한 내용은 여기 에서 확인할 수 있습니다.

cpp -v /dev/null -o /dev/null

Apple LLVM 버전 10.0.0 (clang-1000.10.44.2)
대상 : x86_64-apple-darwin18.0.0
스레드 모델 : posix InstalledDir : 라이브러리 / 개발자 / CommandLineTools / usr / bin
"/ Library / Developer / CommandLineTools / usr / bin / clang"-cc1 -triple x86_64-apple-macosx10.14.0 -Wdeprecated-objc-isa-usage -Werror = 지원 중단됨 -objc-isa-usage -E -disable-free- disable-llvm-verifier -discard-value-names -main-file-name null -mrelocation-model pic -pic-level 2 -mthread-model posix -mdisable-fp-elim -fno-strict-return -masm -verbose - munwind-tables -target-cpu penryn -dwarf-column-info -debugger-tuning = lldb -target-linker -version 409.12 -v -resource-dir /Library/Developer/CommandLineTools/usr/lib/clang/10.0.0 - isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk -I / usr / local / include -fdebug-compilation-dir / 사용자 / hogstrom -ferror-limit 19 -fmessage-length 80 -stack-protector 1 -fblocks -fencode-extended-block-signature -fobjc-runtime = macosx-10.14.0 -fmax-type-align = 16 -fdiagnostics-show-option -fcolor-diagnostics -raditional-cpp -o -xc / dev / null
clang -cc1 버전 10.0.0 (clang-1000.10.44.2) 기본 대상 x86_64-apple-darwin18.0.0 존재하지 않는 디렉토리 "/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/local/include"가 존재하지 않음을 무시합니다. 디렉토리 "/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/Library/Frameworks"#include "
..."여기서 검색 시작 :
#include <...> 여기서 시작 검색 :
/ usr / local / include
/ 라이브러리 / 개발자 / CommandLineTools / usr / lib / clang / 10.0.0 / include
/ 라이브러리 / 개발자 / CommandLineTools / usr / include
/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include/
라이브러리 / 개발자 / CommandLineTools / SDKs / MacOSX10.14.sdk / System / Library / Frameworks (프레임 워크 디렉토리)
검색 목록의 끝.


#include "filename" // User defined header
#include <filename> // Standard library header.

예:

여기서 파일 이름은 Seller.h .

#ifndef SELLER_H     // Header guard
#define SELLER_H     // Header guard

#include <string>
#include <iostream>
#include <iomanip>

class Seller
{
    private:
        char name[31];
        double sales_total;

    public:
        Seller();
        Seller(char[], double);
        char*getName();

#endif

클래스 구현 (예 : Seller.cppSeller.cpp 파일을 사용할 다른 파일)에서는 다음과 같이 사용자가 정의한 헤더가 포함되어야합니다.

#include "Seller.h"

#include <abc.h>

표준 라이브러리 파일을 포함하는 데 사용됩니다. 따라서 컴파일러는 표준 라이브러리 헤더가있는 위치를 체크인합니다.

#include "xyz.h"

사용자 정의 헤더 파일을 포함하도록 컴파일러에 지시합니다. 따라서 컴파일러는 현재 폴더 또는 -I 정의 된 폴더에서 이러한 헤더 파일을 검사합니다.





c-preprocessor