Trình biên dịch của bạn vừa cố gắng biên dịch tệp có tên foo.cc
. Khi nhấn số dòng line
, trình biên dịch tìm thấy:
#include "bar"
hoặc là
#include <bar>
Sau đó, trình biên dịch sẽ cố gắng tìm tệp đó. Đối với điều này, nó sử dụng một tập hợp các thư mục để xem xét, nhưng trong tập hợp này, không có tệp bar
. Để có lời giải thích về sự khác biệt giữa các phiên bản của câu lệnh include, hãy xem tại đây .
Cách thông báo cho trình biên dịch biết nơi tìm nó
g++
có một tùy chọn -I
. Nó cho phép bạn thêm bao gồm các đường dẫn tìm kiếm vào dòng lệnh. Hãy tưởng tượng rằng tệp của bạn bar
nằm trong một thư mục có tên frobnicate
, liên quan đến foo.cc
(giả sử bạn đang biên dịch từ thư mục foo.cc
được đặt):
g++ -Ifrobnicate foo.cc
Bạn có thể thêm nhiều đường dẫn bao gồm hơn; mỗi bạn cung cấp là tương đối với thư mục hiện tại. Trình biên dịch của Microsoft có tùy chọn tương quan /I
hoạt động theo cách tương tự hoặc trong Visual Studio, các thư mục có thể được đặt trong Trang thuộc tính của Dự án, trong Thuộc tính cấu hình-> C / C ++ -> Chung-> Thư mục Bao gồm Bổ sung.
Bây giờ, hãy tưởng tượng bạn có nhiều phiên bản bar
trong các thư mục khác nhau, đã cho:
#include<string>
std::string which() { return "A/bar"; }
#include<string>
std::string which() { return "B/bar"; }
#include<string>
std::string which() { return "C/bar"; }
#include "bar"
#include <iostream>
int main () {
std::cout << which() << std::endl;
}
Mức độ ưu tiên ở ngoài #include "bar"
cùng bên trái:
$ g++ -IA -IB -IC foo.cc
$ ./a.out
A/bar
Như bạn thấy, khi trình biên dịch bắt đầu nhìn qua A/
, B/
và C/
, nó dừng lại ở các hit tận cùng bên trái đầu tiên hoặc.
Điều này đúng với cả hai dạng, include <>
và incude ""
.
Sự khác biệt giữa #include <bar>
và#include "bar"
Thông thường, #include <xxx>
nó làm cho nó nhìn vào các thư mục hệ thống trước, #include "xxx"
làm cho nó nhìn vào các thư mục hiện tại hoặc tùy chỉnh trước.
Ví dụ:
Hãy tưởng tượng bạn có các tệp sau trong thư mục dự án của mình:
list
main.cc
với main.cc
:
#include "list"
....
Đối với điều này, trình biên dịch của bạn sẽ #include
tệp list
trong thư mục dự án của bạn, vì nó hiện đang biên dịch main.cc
và có tệp đó list
trong thư mục hiện tại.
Nhưng với main.cc
:
#include <list>
....
và sau đó g++ main.cc
, trình biên dịch của bạn sẽ xem xét các thư mục hệ thống trước tiên và vì <list>
là tiêu đề tiêu chuẩn, nó sẽ #include
đặt tên tệp list
đi kèm với nền tảng C ++ của bạn như một phần của thư viện tiêu chuẩn.
Tất cả điều này được đơn giản hóa một chút, nhưng sẽ cung cấp cho bạn ý tưởng cơ bản.
Chi tiết về <>
/ ""
-priorities và-I
Theo tài liệu gcc , mức độ ưu tiên đối với include <>
, trên "hệ thống Unix thông thường", như sau:
/usr/local/include
libdir/gcc/target/version/include
/usr/target/include
/usr/include
Đối với các chương trình C ++, trước tiên, nó cũng sẽ tìm trong / usr / include / c ++ / version. Ở trên, target là tên chuẩn của hệ thống mà GCC đã được định cấu hình để biên dịch mã cho; [...].
Tài liệu cũng nêu rõ:
Bạn có thể thêm vào danh sách này với tùy chọn dòng lệnh -Idir. Tất cả các thư mục được đặt tên bởi -I được tìm kiếm, theo thứ tự từ trái sang phải, trước các thư mục mặc định . Ngoại lệ duy nhất là khi dir đã được tìm kiếm theo mặc định. Trong trường hợp này, tùy chọn bị bỏ qua và thứ tự tìm kiếm các thư mục hệ thống không thay đổi.
Để tiếp tục #include<list> / #include"list"
ví dụ của chúng tôi (cùng một mã):
g++ -I. main.cc
và
#include<list>
int main () { std::list<int> l; }
và thực sự, -I.
thư mục ưu tiên .
hơn hệ thống bao gồm và chúng tôi gặp lỗi trình biên dịch.