c++ - ما الفرق بين#include<filename>و#include "filename"؟




header-files c-preprocessor (25)

في لغات برمجة C و C ++ ، ما هو الفرق بين استخدام أقواس زاوية واستخدام علامات اقتباس في عبارة include ، كما يلي؟

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

Answers

شكرا على الإجابات الرائعة ، esp. آدم Stelmaszczyk و piCookie ، و aib.

مثل العديد من المبرمجين ، لقد استخدمت الاتفاقية غير الرسمية لاستخدام نموذج "myApp.hpp" للملفات الخاصة بالتطبيق ، و <libHeader.hpp> النموذج لملفات نظام المكتبة والمترجم ، أي الملفات المحددة في /I ومتغير بيئة INCLUDE ، لسنوات يعتقد أن هذا هو المعيار.

ومع ذلك ، ينص المعيار C على أن أمر البحث محددًا للتنفيذ ، مما يجعل قابلية النقل معقدة. ولجعل الأمور أكثر سوءًا ، نستخدم المربى ، والتي تحدد تلقائيًا أين توجد ملفات التضمين. يمكنك استخدام المسارات النسبية أو المطلقة لملفات التضمين الخاصة بك. أي

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

تتطلب الإصدارات القديمة من MSVS خطوط مائلة عكسية مزدوجة (\\) ، ولكن الآن هذا غير مطلوب. لا أعرف متى تغيرت. ما عليك سوى استخدام خطوط مائلة للأمام للتوافق مع 'nix (سيقبل Windows ذلك).

إذا كنت قلقًا حقًا حيال ذلك ، استخدم "./myHeader.h" لملف التضمين في نفس الدليل "./myHeader.h" المصدر (يحتوي مشروعي الحالي والكبير جدًا على بعض أسماء الملفات المبعثرة المبعثرة - في الحقيقة مشكلة في إدارة التهيئة ).

هنا هو تفسير MSDN نسخها هنا من أجل راحتك).

شكل مقتبس

تتضمن عمليات البحث المسبقة عن الملفات في هذا الترتيب:

  1. في نفس الدليل مثل الملف الذي يحتوي على العبارة #include.
  2. في الدلائل من الملفات المفتوحة حاليا تشمل الملفات ، في الترتيب العكسي فيه
    تم فتحها. يبدأ البحث في دليل الملف الأصلي للملف و
    يستمر صعودا من خلال أدلة أي جد تشمل الملفات.
  3. على طول المسار المحدد بواسطة كل خيار /I compiler.
  4. على طول المسارات المحددة بواسطة متغير البيئة INCLUDE .

شكل زاوية القوس

تتضمن عمليات البحث المسبقة عن الملفات في هذا الترتيب:

  1. على طول المسار المحدد بواسطة كل خيار /I compiler.
  2. عندما يحدث التحويل البرمجي في سطر الأوامر ، على طول المسارات المحددة بواسطة متغير البيئة INCLUDE .

  #include <filename>   (1)     
  #include "filename"   (2)

#include تتضمن الملف المصدر ، الذي تم تحديده بواسطة اسم الملف ، في الملف المصدر الحالي في السطر مباشرة بعد التوجيه.

يتضمن الإصدار الأول من التوجيه البحث القياسي فقط الدلائل. يتم تضمين مكتبة C ++ القياسية ، وكذلك مكتبة C القياسية ، ضمنيًا في الدلائل القياسية وتشمل. المعيار تشمل أدلة يمكن التحكم من قبل المستخدم من خلال خيارات مترجم.

يبحث الإصدار الثاني أولاً الدليل حيث يوجد الملف الحالي و ، فقط إذا لم يتم العثور على الملف ، يبحث في الدلائل القياسية تتضمن.

في حالة عدم العثور على الملف ، يكون البرنامج غير سليم.


يتضمن <file> include المعالج الأولي للبحث في -I الأدلة وفي الدلائل المعرّفة مسبقًا أولاً ، ثم في ملف .c file. يتضمن "file" على المعالج الأولي البحث في دليل الملف المصدر أولاً ، ثم الرجوع إلى -I مسبق. يتم البحث عن جميع الوجهات على أي حال ، يختلف ترتيب البحث فقط.

يناقش معيار 2011 غالبًا ملفات التضمين في "تضمين ملف المصدر 16.2".

2 تعليمات مسبقة من النموذج

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

يبحث عن تسلسل للأماكن المحددة للتنفيذ لرأس محدد بشكل فريد بالتسلسل المحدد بين <و> المحددات ، ويؤدي إلى استبدال هذا التوجيه بمحتويات الرأس بأكملها. كيفية تحديد الأماكن أو تحديد الرأس المحدد بالتنفيذ.

3 تعليمة مسبقة من النموذج

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

يتسبب في استبدال هذا التوجيه بواسطة محتويات الملف المصدر المحددة بواسطة التسلسل المحدد بين "المحددات. يتم البحث عن الملف المصدر المحدد بطريقة محددة بالتطبيق. إذا لم يكن هذا البحث مدعومًا ، أو إذا فشل البحث ، إعادة معالجة التوجيه كما لو كان يقرأ

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

مع التسلسل المتضمن المتضمن (بما في ذلك> الأحرف ، إن وجدت) من التوجيه الأصلي.

لاحظ أن نموذج "xxx" degrades إلى نموذج <xxx> إذا لم يتم العثور على الملف. الباقي هو تعريف التنفيذ.


بالنسبة إلى #include "filename" ، يبحث المعالج الأولي في نفس الدليل مثل الملف الذي يحتوي على التوجيه. يتم استخدام هذه الطريقة عادةً لتضمين ملفات رأس مبرمج المعرفة.

ل # تتضمن عمليات البحث preprocessor بطريقة تعتمد على التنفيذ ، عادة في أدلة البحث المعينة مسبقا من قبل المترجم / IDE. يتم استخدام هذه الطريقة عادةً لتضمين ملفات رأس مكتبة قياسية.


#include <filename>

will find the corresponding file from the C++ library. it means if you have a file called hello.h in the C++ library folder, #include <hello.h> will load it.

لكن،

#include "filename"

will find the file in the same directory where your source file is.

In addition,

#include "path_to_file/filename"

will find the file in the directory which you typed in path_to_file .


في C ++ ، تضمين ملف بطريقتين:

أول واحد هو تضمين # الذي يخبر المعالج الأولي للبحث عن الملف في الموقع الافتراضي المحدد مسبقًا. هذا الموقع هو غالباً متغير بيئة INCLUDE الذي يشير إلى المسار لتضمين الملفات.

والنوع الثاني هو #include "filename" الذي يخبر المعالج الأولي أن يبحث عن الملف في الدليل الحالي أولاً ، ثم يبحث عنه في المواقع المحددة مسبقًا التي قام المستخدم بإعدادها.


تقول وثائق دول مجلس التعاون الخليجي ما يلي حول الفرق بين الاثنين:

يتم تضمين كل من ملفات رأس المستخدم والنظام باستخدام الأمر preprocessing '#include' . لديها اثنين من المتغيرات:

#include <file>

يتم استخدام هذا المتغير لملفات رأس النظام. يبحث عن ملف يسمى ملف في قائمة قياسية من دلائل النظام. يمكنك الإحاطة بالأدلة إلى هذه القائمة مع خيار -I (انظر Invocation ).

#include "file"

يستخدم هذا المتغير لملفات رأس البرنامج الخاص بك. يبحث عن ملف اسمه ملف أولاً في الدليل الذي يحتوي على الملف الحالي ، ثم في الدلائل إقتباس ومن ثم نفس الدلائل المستخدمة <file> . يمكنك توجيه الأدلة إلى قائمة دلائل الاقتباس مع خيار -iquote . تتصرف حجة '#include' ، سواء كانت محددة بعلامات اقتباس أو أقواس زاوية ، مثل ثابت سلسلة في تلك التعليقات غير معترف بها ، ولا يتم توسيع أسماء الماكرو. وبالتالي ، يحدد #include <x/*y> تضمين ملف رأس النظام المسمى x/*y .

ومع ذلك ، إذا حدثت خطوط مائلة عكسية داخل الملف ، فستعتبر أحرفًا نصية عادية ، وليست أحرف هروب. يتم معالجة أي من تسلسل الهروب حرف المناسبة ثوابت السلسلة في C. وبالتالي ، يحدد #include "x\n\\y" اسم ملف يحتوي على ثلاث خطوط مائلة عكسية. (تفسر بعض الأنظمة '\' كفاصل اسم مسار. كل هذه تفسر أيضًا '/' بنفس الطريقة. إنها أكثر قابلية للحمل للاستخدام فقط '/' .)

إنه خطأ إذا كان هناك أي شيء (بخلاف التعليقات) على السطر بعد اسم الملف.


القاعدة العامة البسيطة هي استخدام الأقواس المائلة لتضمين ملفات الرأس التي تأتي مع المحول البرمجي. استخدم علامات الاقتباس المزدوجة لتضمين أي ملفات رأس أخرى. معظم المترجمين يقومون بذلك بهذه الطريقة.

1.9 - تشرح ملفات الرأس بمزيد من التفاصيل حول توجيهات ما قبل المعالج. إذا كنت مبرمج مبتدئًا ، فيجب أن تساعدك هذه الصفحة في فهم كل ذلك. تعلمت ذلك من هنا ، وأنا أتابعه في العمل.


#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.cpp ، وفي الملفات الأخرى التي ستستخدم الملف Seller.h ) ، يجب الآن تضمين العنوان المحدد من قبل المستخدم ، كما يلي:

#include "Seller.h"

سيشمل # تضمين مع أقواس زاوية "قائمة بالأماكن المعتمدة على التنفيذ" (وهي طريقة معقدة جدًا لقول "رؤوس النظام") لتضمين الملف.

سوف تتضمن # تضمين مع علامات اقتباس فقط ابحث عن ملف (و ، "بطريقة تعتمد على التنفيذ" ، bleh). وهو ما يعني ، في اللغة الإنجليزية العادية ، أنه سيحاول تطبيق المسار / اسم الملف الذي تقوم بإلقائه فيه ولن يقوم بملء مسار النظام أو العبث به بطريقة أخرى.

أيضًا ، إذا فشل #include "" ، فسيتم إعادة قراءته كـ #include <> حسب المعيار.

تحتوي g++ على وصف (خاص بالمتحول) والذي على الرغم من كونه مخصصًا لدول مجلس التعاون الخليجي وليس المعيار ، يكون من الأسهل فهمه أكثر من حديث أسلوب المحاماة لمعايير ISO.


الطريقة الوحيدة لمعرفة ذلك هي قراءة وثائق التنفيذ الخاصة بك.

في المعيار C ، الفقرة 6.10.2 ، تنص الفقرات 2 إلى 4 على:

  • توجيه مسبق المعالجة للنموذج

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

    يبحث عن تسلسل للأماكن المحددة للتنفيذ لرأس محدد بشكل فريد بالتسلسل المحدد بين < و > المحددات ، ويؤدي إلى استبدال هذا التوجيه بمحتويات الرأس بأكملها. كيفية تحديد الأماكن أو تحديد الرأس المحدد بالتنفيذ.

  • توجيه مسبق المعالجة للنموذج

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

    يتسبب استبدال هذا التوجيه من خلال محتويات الملف المصدر المحددة بواسطة التسلسل المحدد بين " المحددات. يتم البحث عن الملف المصدر المحدد بطريقة محددة بالتنفيذ. إذا لم يكن هذا البحث مدعومًا ، أو إذا فشل البحث ، إعادة معالجة التوجيه كما لو كان يقرأ

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

    مع التسلسل المتضمن المتضمن (بما في ذلك > الأحرف ، إن وجدت) من التوجيه الأصلي.

  • توجيه مسبق المعالجة للنموذج

    #include pp-tokens new-line
    

    (لا يتطابق أحد النموذجين السابقين) مسموح به. تتم معالجة الرموز المميزة السابقة للتنفيذ بعد include في التوجيه كما هو الحال في النص العادي. (يتم استبدال كل معرف يتم تعريفه حاليًا كاسم ماكرو بقائمة الاستبدال الخاصة برموز المعالجة المسبقة.) التوجيه الناتج بعد أن تكون جميع عمليات الاستبدال مطابقة لأحد النموذجين السابقين. الطريقة التي يتم بها تجميع تسلسل رموز التهيئة المسبقة بين زوج الرمز المميز > pre > أو زوج من " الأحرف " في اسم مميز برمجية ذات اسم وحيد.

تعريفات:

  • h-char: أي عضو في مجموعة أحرف المصدر باستثناء حرف السطر الجديد و >

  • q-char: أي عضو في مجموعة أحرف المصدر باستثناء حرف السطر الجديد و "


يتم استخدام #include <filename> عند الإشارة إلى ملف نظام. هذا هو ملف رأس يمكن العثور عليه في المواقع الافتراضية للنظام مثل /usr/include أو /usr/local/include . لملفاتك الخاصة التي تحتاج إلى تضمينها في برنامج آخر ، عليك استخدام الصيغة #include "filename" .


To include a predefined library header file , #include<filename> is used whereas to include user defined header file, #include "filename" is relevant.


من الناحية العملية ، يكون الاختلاف في الموقع الذي يبحث فيه المعالج الأولي عن الملف المضمن.

بالنسبة إلى #include <filename> ، يبحث المعالج الأولي بطريقة تعتمد على التنفيذ ، عادةً في دلائل البحث المعينة مسبقًا بواسطة المترجم / IDE. يتم استخدام هذه الطريقة عادةً لتضمين ملفات رأس مكتبة قياسية.

بالنسبة إلى #include "filename" ، يبحث المعالج الأولي أولاً في نفس الدليل مثل الملف الذي يحتوي على التعليمة ، ثم يتبع مسار البحث المستخدم للنموذج #include <filename> . يتم استخدام هذه الطريقة عادةً لتضمين ملفات رأس مبرمج المعرفة.

يتوفر وصف أكثر اكتمالاً في وثائق دول مجلس التعاون الخليجي حول مسارات البحث .


بالنسبة إلى #include "" ، يبحث المحول البرمجي عادةً عن مجلد الملف الذي يحتوي على المجلد ثم المجلدات الأخرى. بالنسبة إلى #include <> ، لا يبحث المحول البرمجي في مجلد الملف الحالي.


بعض الإجابات الجيدة هنا تشير إلى المعيار C ولكن ننسى معيار POSIX ، خاصةً السلوك المعين لقيادة c99 (على سبيل المثال C compiler) .

وفقًا لإصدار مواصفات Open Group Base 7 ،

من الدليل

قم بتغيير الخوارزمية للبحث عن رؤوس لا تكون أسماءها أسماء مسار مطلقة للبحث في الدليل المسمى بواسطة مسار الدليل قبل البحث في الأماكن المعتادة. وبالتالي ، يجب البحث عن العناوين التي تم تضمين أسماؤها بين علامتي اقتباس مزدوجتين ("") لأول مرة في دليل الملف مع سطر #include ، ثم في الدلائل المسماة في خيارات -I ، والأخيرة في الأماكن المعتادة. بالنسبة للرؤوس التي تكون أسماؤها مُحاطة بأقواس زاوية ("<>") ، يجب البحث عن الرأس فقط في الأدلة المسماة بخيارات -I ثم في الأماكن المعتادة. يجب البحث عن الأدلة المذكورة في الخيارات -I بالترتيب المحدد. يجب أن تدعم التنفيذ عشر حالات على الأقل من هذا الخيار في استدعاء أمر واحد c99 .

لذلك ، في بيئة متوافقة مع POSIX ، مع مترجم C متوافق مع POSIX ، من المحتمل أن يبحث #include "file.h" عن ./file.h أولاً ، حيث . هو الدليل حيث يوجد الملف مع العبارة #include ، بينما #include <file.h> ، من المرجح أن يبحث عن /usr/include/file.h أولاً ، حيث /usr/include هو نظامك المحدد للأماكن المعتادة لـ الرؤوس (يبدو أنه لم يتم تعريفه بواسطة POSIX).


أعتقد أنه سيتم البحث عن الرؤوس المضمنة في علامات الاقتباس المزدوجة في نفس مسارات النظام ، حيث تتضمن الزاوية بين قوسين إذا لم يتم العثور عليها في الدليل الحالي.


#include <file> tells the compiler to search for the header in its includes directory, eg for MinGW the compiler would search for file in C:\MinGW\include\ or wherever your compiler is installed.

#include "file" tells the compiler to search the current directory (ie the directory in which the source file resides) for file .

You can use the -I flag for GCC to tell it that, when it encounters an include with angled brackets, it should also search for headers in the directory after -I . For instance, if you have a file called myheader.h in your own directory, you could say #include <myheader.h> if you called GCC with -I . (indicating that it should search for includes in the current directory.)


على الأقل بالنسبة لإصدار GCC <3.0 ، لا يقوم نموذج قوس الزاوية بإنشاء تبعية بين الملف المضمن وبين الملف المرفق.

لذا إذا كنت تريد إنشاء قواعد التبعية (باستخدام خيار GCC -M للعرض) ، يجب استخدام النموذج المقتبس للملفات التي يجب تضمينها في شجرة التبعية.

(راجع http://gcc.gnu.org/onlinedocs/cpp/Invocation.html )


When you use #include <filename>, the pre-processor looking for the file in directtory of C\C++ header files (stdio.h\cstdio, string, vector, etc.). But, when you use #include "filename": first, the pre-processor looking for the file in the current directory, and if it doesn't here - he looking for it in the directory of C\C++ header files.


the " < filename > " searches in standard C library locations

whereas "filename" searches in the current directory as well.

Ideally, you would use <...> for standard C libraries and "..." for libraries that you write and are present in the current directory.


حسب المعيار - نعم ، فهي مختلفة:

  • توجيه مسبق المعالجة للنموذج

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

    يبحث عن تسلسل للأماكن المحددة للتنفيذ لرأس محدد بشكل فريد بالتسلسل المحدد بين < و > المحددات ، ويؤدي إلى استبدال هذا التوجيه بمحتويات الرأس بأكملها. كيفية تحديد الأماكن أو تحديد الرأس المحدد بالتنفيذ.

  • توجيه مسبق المعالجة للنموذج

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

    يتسبب في استبدال هذا التوجيه بواسطة محتويات الملف المصدر المحددة بواسطة التسلسل المحدد بين " المحددات. يتم البحث عن الملف المصدر المحدد بطريقة محددة بالتطبيق. إذا لم يكن هذا البحث مدعومًا ، أو إذا فشل البحث ، إعادة معالجة التوجيه كما لو كان يقرأ

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

    مع التسلسل المتضمن المتضمن (بما في ذلك > الأحرف ، إن وجدت) من التوجيه الأصلي.

  • توجيه مسبق المعالجة للنموذج

    #include pp-tokens new-line
    

    (لا يتطابق أحد النموذجين السابقين) مسموح به. تتم معالجة الرموز المميزة السابقة للتنفيذ بعد include في التوجيه كما هو الحال في النص العادي. (يتم استبدال كل معرف يتم تعريفه حاليًا كاسم ماكرو بقائمة الاستبدال الخاصة برموز المعالجة المسبقة.) التوجيه الناتج بعد أن تكون جميع عمليات الاستبدال مطابقة لأحد النموذجين السابقين. الطريقة التي يتم بها تجميع تسلسل رموز التهيئة المسبقة بين زوج الرمز المميز > pre > أو زوج من " الأحرف " في اسم مميز برمجية ذات اسم وحيد.

تعريفات:

  • h-char: أي عضو في مجموعة أحرف المصدر باستثناء حرف السطر الجديد و >

  • q-char: أي عضو في مجموعة أحرف المصدر باستثناء حرف السطر الجديد و "

لاحظ أن المعيار لا يخبر أي علاقة بين الأخلاقيات المحددة للتنفيذ. يبحث النموذج الأول في طريقة واحدة محددة بالتنفيذ ، والآخر بطريقة (قد تكون أخرى) محددة للتنفيذ. تحدد المواصفة أيضًا أن بعض الملفات المضمنة يجب أن تكون موجودة (على سبيل المثال ، <stdio.h> ).

بشكل رسمي يجب عليك قراءة دليل المترجم الخاص بك ، ولكن عادة (حسب التقليد) يبحث النموذج #include "..." في دليل الملف الذي تم العثور فيه على #include تم #include أولاً ، ثم الدلائل أن #include <...> عمليات البحث عن النموذج (مسار التضمين ، على سبيل المثال ، رؤوس النظام).


تركز العديد من الإجابات هنا على المسارات التي يبحث عنها المترجم للعثور على الملف. في حين أن هذا هو ما يفعله معظم المترجمين ، فإنه يُسمح بتجميع مترجم مطابق مع تأثيرات الرؤوس القياسية ، وعلاجه ، على سبيل المثال ، #include <list> كمحول ، ولا يلزم وجوده كملف على الإطلاق.

هذه ليست افتراضية بحتة. يوجد مترجم واحد على الأقل يعمل بهذه الطريقة. ينصح باستخدام #include <xxx> فقط بالرؤوس القياسية.


#include <filename>

عند الرغبة في استخدام ملف الرأس الخاص بنظام C / C ++ أو مكتبات المترجم. يمكن أن تكون هذه المكتبات stdio.h ، string.h ، math.h ، إلخ.

#include "path-to-file/filename"

عند الرغبة في استخدام ملف الرأس المخصص الخاص بك الموجود في مجلد المشروع أو في مكان آخر.

لمزيد من المعلومات حول preprocessors والرأس. قراءة C - Preprocessors .


كتاب واحد قرأته (لا أتذكر بشكل صحيح أي كتاب) ذكر: يحاول Compilers تحليل التعبيرات إلى الرمز المميز الأكبر باستخدام القاعدة اليمنى اليسرى.

في هذه الحالة ، التعبير:

x-->0

يوزع على أكبر الرموز:

token 1: x
token 2: --
token 3: >
token 4: 0
conclude: x-- > 0

تنطبق القاعدة نفسها على هذا التعبير:

a-----b

بعد التحليل:

token 1: a
token 2: --
token 3: --
token 4: -
token 5: b
conclude: (a--)-- - b

آمل أن يساعد هذا على فهم تعبير معقد ^^





c++ c include header-files c-preprocessor