عبر الإنترنت بما في ذلك ملف مصدر C إلى آخر؟ الترجمة بما في ذلك ملف مصدر C إلى آخر؟ ما يمكن أن يكون في ملف التنفيذ

لقد سُئل مؤخرًا سؤال مماثل من قبل زميل كان قد بدأ البرمجة بلغة C. وأعتقد أن هذه كانت فرصة جيدة لمشاركة فهمي لهذه القضية. لأنه حتى المبرمجين ذوي الخبرة ليس لديهم دائمًا وجهات نظر مماثلة حول هذه المسألة.

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

على الرغم من أن "الحقيقة الكاملة" حول ملفات h موجودة في القسم المقابل من وصف المعالج المسبق لدول مجلس التعاون الخليجي، فسوف أسمح لنفسي ببعض التوضيحات والرسوم التوضيحية.

لذلك، حرفيًا، ملف الرأس (h-file) هو ملف يحتوي على إعلانات C وتعريفات الماكرو المخصصة للاستخدام في العديد من الملفات المصدر (c-files). دعونا نوضح هذا.

من السهل ملاحظة أن الوظيفتين 1 و2، بالإضافة إلى الماكرو 2، مذكورتان في كلا الملفين. وبما أن تضمين ملفات الرأس يؤدي إلى نفس نتائج نسخ المحتويات إلى كل ملف C، فيمكننا القيام بما يلي:

وبالتالي، قمنا ببساطة باستخراج الجزء المشترك من الملفين ووضعه في الملف الرأسي.
ولكن هل يعتبر ملف الرأس واجهة في هذه الحالة؟

  • إذا أردنا استخدام الوظيفة التي تنفذ الدالتين 1 و2 في مكان آخر، فنعم
  • إذا كان الماكرو 2 مخصصًا للاستخدام فقط في ملفات Unit1.c وUnit2.c، فلا مكان له في ملف الواجهة
علاوة على ذلك، هل نحتاج حقًا إلى ملفين بلغة C لتنفيذ الواجهة المحددة في ملف الرأس؟ أم أن واحدة كافية؟
تعتمد الإجابة على هذا السؤال على تفاصيل تنفيذ وظائف الواجهة ومكان تنفيذها. على سبيل المثال، إذا قمت بجعل المخططات أكثر تفصيلاً، فيمكنك تخيل سيناريو يتم فيه تنفيذ وظائف الواجهة في ملفات مختلفة:


يؤدي خيار التنفيذ هذا إلى تماسك عالي للتعليمات البرمجية وانخفاض قابلية الاختبار والتعقيد. إعادة استخداممثل هذه الوحدات.
لتجنب مثل هذه الصعوبات، أعتبر دائمًا ملف C وملف الرأس كوحدة واحدة. بحيث،
  • يحتوي ملف الرأس فقط على إعلانات الوظائف والأنواع ووحدات الماكرو التي تشكل جزءًا من واجهة هذه الوحدة.
  • يجب أن يحتوي ملف C بدوره على تنفيذ جميع الوظائف المعلنة في ملف h، بالإضافة إلى الأنواع الخاصة ووحدات الماكرو والوظائف اللازمة لتنفيذ الواجهة.
وبالتالي، إذا كنت سأقوم بتنفيذ الكود الذي يتوافق مع الرسم البياني أعلاه، فسأحاول تحقيق ما يلي (تمت إضافة النهايات _c و _h في أسماء الملفات بسبب استحالة استخدام نقطة في الأداة التي استخدمتها لإنشاء المخططات):


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

آمل أن أتمكن من تحديد تلك الكيانات التي يجب وضعها في ملفات الرأس. وأيضا توضيح الفرق بين الواجهات والملفات التي تحتوي على التصريحات ووحدات الماكرو التي تتطلبها عدة ملفات C.

شكرا لاهتمامكم بالمادة.

support.microsoft

عند تعديل الملفات المصدر في Visual C++ وحفظها، يجب أن تنتهي الأسطر بتركيبة "CR/LF" [سطر الإرجاع، تغذية السطر]. في أنظمة UNIX، يتم إنهاء الخطوط بـ "LF". وهكذا، عند عرض الملفات التي تم تعديلها في مجموعة ويندوزفي أنظمة UNIX، قد تظهر العديد من الأحرف "^M" في السلاسل. يحدث هذا فقط عند استخدام محرر لا يعرف كيفية التفسير ملف ويندوز. يمكن لـ Visual C++ فتح الملفات ذات الأسطر التي تنتهي بإنشاء UNIX LF. إذا قمت بتغيير هذا الملف وحفظه من Visual C++، فسيتم حفظه في تنسيق ويندوز(سترى CR/LF وليس LF الذي كان موجودًا مسبقًا في النظام).

توضح هذه المقالة إجراءات حفظ ملف معدل تم إنشاؤه على النظام الأساسي لـ Windows بتنسيق يمكن استخدامه على أنظمة UNIX.

ملحوظة: يحتوي Visual C++.NET IDE على الوظائف المتاحة لحفظ ملف بتنسيق UNIX. في IDE، احفظ الملف باستخدام حفظ باسم...، حدد حفظ من القائمة المنسدلة حفظ بالتشفير...، واضغط على زر thrn نعم. حدد ترميز السلسلة من القائمة المنسدلة يونيكس (LF)ومن ثم انقر فوق الزر نعم.

ممكن استخدامه الخطوات التاليةلإنشاء مشروع تطبيق وحدة تحكم Win32 الذي يحول ملفًا يحتوي على "CR/LF" إلى سطر ينتهي بـ "LF":

  1. لإنشاء واحدة جديدة باستخدام تطبيقات وحدة التحكممشروع Win32 فارغ اسمه DOS2UNIX.
  2. من ملفالقائمة، اضغط على الزر جديدومن ثم انقر فوق الزر ملفاتفاتورة غير مدفوعة.
  3. يختار الملف الأصليج/ج++وأدخل اسم الملف الجديد DOS2UNIX.cpp.
  4. الصق التعليمة البرمجية التالية في DOS2UNIX.cpp:

    #يشمل #يشمل #يشمل استخدام اسم للمحطة؛ int main(int argc, char* argv) ( if(argc !=2) ( cout<< "Please specify: dos2unix filename" << endl; return 0; } char ch; char temp="\0"; //Open the file for reading in binarymode. ifstream fp_read(argv, ios_base::in \ / ios_base::binary); sprintf(temp, "%s.temp", argv); //Create a temporary file for writing in the binary mode. This //file will be created in the same directory as the input file. ofstream fp_write(temp, ios_base::out \ / ios_base::trunc \ / ios_base::binary); while(fp_read.eof() != true) { fp_read.get(ch); //Check for CR (carriage return) if((int)ch == 0x0D) continue; if (!fp_read.eof())fp_write.put(ch); } fp_read.close(); fp_write.close(); //Delete the existing input file. remove(argv); //Rename the temporary file to the input file. rename(temp, argv); //Delete the temporary file. remove(temp); return 0; }

  5. من بناءالقائمة، اضغط على الزر إنشاء DOS2UNIX.exeلإنشاء ملف EXE.

قد تحتاج إلى اختبار ملف exe هذا لمعرفة ما إذا كان يعمل بشكل صحيح. للقيام بذلك، افتح الملف في محرر Visual C++ الثنائي عند التحديد يفتحفي مجموعة ملفالقائمة عن طريق تحديد DOS2UNIX.ex، الإعدادات افتح كإلى من الثنائيةومن ثم النقر يفتح. على سبيل المثال، إذا كان الملف يحتوي على "hellocrlfworld"، فستبدو بيانات الملف الثنائي (الست عشري) كما يلي:

48 65 6 ج 6 ج 6 ف 0 د 0 أ 57 6 ف 72 6 ج 64

وهذا يعادل:

مرحبًا
عالم

في موجه الأوامر، قم بتشغيل dos2unix.exe . بعد ذلك، افتح الملف في المحرر الثنائي Visual C++. سترى أنه تمت إزالة 0x0d s. حتى تقوم بتغيير الملف وحفظه في Visual C++ 0x0d s لن يظهر.

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

  1. من خدمةالقائمة، اضغط على الزر إعداداتومن ثم انقر فوق الزر خدمةفاتورة غير مدفوعة.
  2. قم بتوفير اسم مثل DOS2UNIX وقم بتوفير المسار الكامل لملف Dos2unix.exe في فريقتحرير المجال.
  3. قم بتعيين الوسيطة إلى $(Filename)$(FileExt).
  4. حدد الدليل المصدر $(WkspDir) (حدد المسار الخاص بك).

للتحقق من عمل البرنامج، افتح الملف في محرر Visual C++، ثم من خدمةقائمة البدأ DOS2UNIXوسائل. ستلاحظ أن الملف المفتوح في المحرر قد تمت إزالة كافة أحرف السجل التجاري الخاصة به.

إذا كنت تريد أتمتة هذه العملية، فتعامل معها بحيث يتم استدعاء DOS2UNIX.exe في كل مرة تحفظ فيها ملفًا مفتوحًا في محرر Visual C++ لإزالة 0x0d s، ثم استخدم ماكرو VBScript التالي:

"يتم تشغيل هذا الحدث في كل مرة يتم فيها حفظ المستند في محرر VC++. Sub Application_DocumentSave(theDocument) "سيقوم هذا باستدعاء أداة المستخدم في قائمة "الأدوات". "قم بتغيير الرقم اعتمادًا على ما لديك. بشكل افتراضي، لديك 6 أدوات فقط ضمن قائمة الأدوات، لذا ستكون أداة DOS2UNIX هي الأداة السابعة. تنفيذ الأمر "UserTool7" End Sub

لن يعمل رمز VBScript هذا إلا إذا كان لديك ملفات مفتوحة في محرر Visual C++. هذه هي الطريقة الوحيدة لاستدعاء ملف exe من ماكرو VBScript (لا يمكن تمرير معلمات لوحدات ماكرو VBScript). يمكنك الكتابة بدلاً من ذلك وسيكون الأمر أكثر مرونة. اتصل بأداة "DOS2UNIX.exe" من وظيفة إضافية دون الحاجة إلى إضافتها إليها خدمةقائمة طعام.

في Visual C++ باستخدام ماكرو VBScript المتوفر:

  1. افتح ملفًا موجودًا بامتداد .dsm أو قم بإنشاء ملف.
  2. الصق الكود الذي تم تقديمه مسبقًا في الملف.
  3. في Visual C++، قم بما يلي:
    1. من خدمةالقائمة، اضغط على الزر إعدادات.
    2. انقر فوق الزر ملفات الماكرو والوظائف الإضافيةفاتورة غير مدفوعة.
    3. انقر فوق الزر مراجعةقم بتحميل ملف .dsm الذي يحتوي على الماكرو. بمجرد تحديد ملف .dsm مراجعةفي مربع الحوار، سيظهر الملف الوظائف الإضافية ووحدات الماكروقائمة الملفات باستخدام مربع الاختيار المحدد بجوارها.
    4. انقر فوق الزر يغلقلاستكمال.

الآن، إذا قمت بفتح الملف في محرر Visual C++ وحفظه من الملف ملفالقائمة، ستتم إزالة الماكرو المطلوب وكل 0x0d s من الملف المفتوح. وبما أن هذا سيؤثر على أي ملف محفوظ من الآن فصاعدا وسيتم تطبيقه على أي مشروع تفتحه في المستقبل، تأكد من تعطيل الماكرو من خدمةالقائمة باستخدام إعدادات(قم بإلغاء تحديد المربع الموجود بجوار الماكرو).



اعتمادًا على بيئة البناء الخاصة بك (لن تحددها) قد تجد أنها تعمل بالطريقة التي تريدها تمامًا.

ومع ذلك، هناك العديد من البيئات (كل من IDEs والعديد من ملفات Makefiles المصنوعة يدويًا) التي تتوقع تجميع *.c - إذا حدث ذلك، فمن المحتمل أن تواجه أخطاء في الرابط بسبب الرموز المكررة.

بشكل عام، ينبغي تجنب هذه الممارسة.

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

يعد تضمين ملف C داخل ملف آخر أمرًا قانونيًا، ولكن لا ينصح به إلا إذا كنت تعرف بالضبط سبب قيامك بذلك وما تحاول تحقيقه.
أنا متأكد تمامًا من أنك إذا نشرت هنا سبب إيصال سؤالك إلى المجتمع، فستجد طريقة أخرى مناسبة لتحقيق هدفك (لاحظ "تقريبًا" لأنه من الممكن أن يكون هذا حلاً، في ضوء السياق ).

بالمناسبة، فاتني الجزء الثاني من السؤال. إذا تم تضمين ملف C في ملف آخر وفي نفس الوقت تم تضمينه في مشروع، فمن المحتمل أن تواجه مشكلة الرموز المكررة، ولماذا ربط الكائنات، أي سيتم تعريف نفس الوظيفة مرتين (ما لم تكن ثابتة).

لا تحظر لغة C هذا النوع من #include، ولكن يجب أن تظل وحدة الترجمة الناتجة صالحة لـ C.

لا أعرف ما هو البرنامج الذي تستخدمه مع الملف .prj. إذا كنت تستخدم شيئًا مثل "make" أو Visual Studio أو أي شيء آخر، فقط تأكد من تعيينه على قائمة الملفات التي تحتاج إلى تجميع بدون ملف لا يمكن تجميعه بشكل مستقل.

يمكنك استخدام برنامج التحويل البرمجي gcc على نظام التشغيل Linux لربط ملفين بمخرج واحد. لنفترض أن لديك ملفين من نوع c، أحدهما هو "main.c" والآخر هو "support.c". لذا فإن الأمر لربط هذين هو

دول مجلس التعاون الخليجي main.c support.c -o main.out

سيتم ربط هذين الملفين بملف main.out واحد. لتشغيل الإخراج سيكون الأمر

./خارج الرئيسية

إذا كنت تستخدم وظيفة main.c التي تم الإعلان عنها في ملف support.c، فيجب عليك الإعلان عنها بشكل رئيسي أيضًا باستخدام فئة التخزين الخارجية.

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

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

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

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

إذا قمت بوضع كل شيء في وحدة مصدر C واحدة، فستحصل على -

    تحسينات في الأداء وحجم التعليمات البرمجية - في العديد من الحالات، سيتم تضمين استدعاءات الوظائف. حتى بدون البطانة، يتمتع المترجم بالقدرة على إنتاج تعليمات برمجية أكثر كفاءة.

    يتم إخفاء مستوى القناة وبيانات الوظيفة.

    تجنب تلوث مساحة الاسم وعواقبه - يمكنك استخدام أسماء أقل تعقيدًا.

    تجميع واتصال أسرع.

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

ومع ذلك، تحتاج إلى فرض بعض الاتفاقيات للتعامل مع هذا. سيعتمد هذا إلى حد ما على سلسلة الأدوات الخاصة بك، ولكن بعض المؤشرات العامة هي كذلك

    ضع الواجهة العامة في ملف رأس منفصل - لا يزال يتعين عليك القيام بذلك.

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

    استخدم حراس المترجم لمنع تضمين الرؤوس الخاصة ووحدات المصدر بواسطة وحدات الترجمة الخارجية.

    يجب إعلان جميع البيانات والوظائف الشخصية ثابتة.

    الحفاظ على التمييز المفاهيمي بين ملفات .c و.h. يستخدم هذا الاتفاقيات الموجودة. الفرق هو أنه سيكون لديك الكثير من الإعلانات الثابتة في رؤوسك.

    إذا كانت سلسلة الأدوات الخاصة بك لا تفرض أي شيء، فلا ينبغي عليك تحديد ملفات التنفيذ الخاصة مثل .c و.h. إذا كنت تستخدم الحراس الممكّنين، فلن يقوموا بإنشاء تعليمات برمجية ولن يقدموا أي أسماء جديدة (قد ينتهي بك الأمر مع بعض المقاطع الفارغة نتيجة لذلك). الميزة الكبيرة هي أن الأدوات الأخرى (مثل IDEs) ستتعامل مع هذه الملفات وفقًا لذلك.

لا يهم امتداد الملف معظم مترجمي لغة C، لذلك سينجح هذا الأمر.

ومع ذلك، اعتمادًا على إعدادات ملفك أو مشروعك، قد يقوم ملف c المضمن بإنشاء ملف كائن منفصل. عند الارتباط، يمكن أن يؤدي ذلك إلى أحرف محددة مزدوجة.

يجب عليك إضافة رأس مثل هذا

#يشمل

ملاحظة: يجب وضع كلا الملفين في نفس المكان

يمكنك تضمين ملفات .C أو .CPP بشكل صحيح في ملفات مصدر أخرى. اعتمادًا على IDE الخاص بك، يمكنك عادةً منع الارتباط المزدوج عن طريق عرض خصائص الملفات المصدر التي تريد تضمينها، عادةً عن طريق النقر بزر الماوس الأيمن عليها والنقر فوق الخصائص، وإلغاء تحديد /تحديد التجميع/الارتباط/الاستبعاد من البناء أو أي شيء آخر خيار . ربما. أو لا يمكنك تضمين الملف في المشروع نفسه، وبالتالي فإن IDE لا يعرف بوجوده ولن يحاول تجميعه. ومع ملفات makefiles، فإنك ببساطة لم تضع الملف فيه لتجميعه وربطه.

تعديل: آسف، لقد قدمت إجابة بدلاً من الإجابة على الإجابات الأخرى :(

ملفات المصدر

يمكن تقسيم نص برنامج C إلى عدة ملفات مصدر. الملف المصدر هو ملف نصي يحتوي إما على البرنامج بأكمله أو جزء منه. عندما يتم تجميع برنامج مصدر، يجب تجميع كل ملف من الملفات المصدر المكونة له بشكل منفصل ثم ربطها بالملفات الأخرى بواسطة الرابط. يمكن دمج ملفات المصدر الفردية في ملف مصدر واحد، وتجميعها كوحدة واحدة، باستخدام توجيهات المعالج المسبق #يشمل.

يمكن أن يحتوي الملف المصدر على أي مجموعة شاملة من التوجيهات وتعليمات المترجم والإعلانات والتعريفات. تعني النزاهة أن الكائنات مثل تعريفات الوظائف، أو هياكل البيانات، أو مجموعة من توجيهات الترجمة الشرطية ذات الصلة يجب أن تتواجد بالكامل في ملف واحد، أي أنها لا يمكن أن تبدأ في ملف واحد وتستمر في ملف آخر.

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

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

في المثال التالي، يتكون البرنامج المصدر من ملفين مصدر. المهام رئيسيو الأعلىالمقدمة في ملفات منفصلة. وظيفة رئيسييستخدم الوظيفة الأعلىفي عملية تنفيذه.

/* الملف المصدر 1 - الوظيفة الرئيسية */

extern int max(int, int); /* إعلان الدالة */

main() /* تعريف الدالة */

int w = ONE, x = TWO, y = THREE;

/* الملف المصدر 2 - الحد الأقصى للوظيفة */

int max (a, b) /* تعريف الدالة */

في الملف المصدر الأول الدالة الأعلىأعلن ولكن لم يتم تحديده. يُسمى إعلان الوظيفة هذا بالإعلان المسبق؛ فهو يسمح للمترجم بالتحكم في استدعاءات الوظيفة قبل تعريفها. تعريف الوظيفة رئيسييحتوي على استدعاءات الوظائف الأعلى.

الأسطر التي تبدأ بالرمز # هي توجيهات ما قبل المعالج. تشير التوجيهات إلى المعالج المسبق بضرورة استبدال المعرفات ONE، TWO، THREE بالقيم المقابلة في الملف المصدر الأول. لا يمتد نطاق التوجيهات إلى الملف المصدر الثاني.



التصويت عبر الإنترنت (8)

يعد تضمين ملف C داخل ملف آخر أمرًا قانونيًا، ولكن لا ينصح به إلا إذا كنت تعرف بالضبط سبب قيامك بذلك وما تحاول تحقيقه.
أنا متأكد تمامًا من أنك إذا نشرت هنا سبب إيصال سؤالك إلى المجتمع، فستجد طريقة أخرى مناسبة لتحقيق هدفك (لاحظ "تقريبًا" لأنه من الممكن أن يكون هذا حلاً، في ضوء السياق ).

بالمناسبة، فاتني الجزء الثاني من السؤال. إذا تم تضمين ملف C في ملف آخر وفي نفس الوقت تم تضمينه في مشروع، فمن المحتمل أن تواجه مشكلة الرموز المكررة، ولماذا ربط الكائنات، أي سيتم تعريف نفس الوظيفة مرتين (ما لم تكن ثابتة).

لا يهم امتداد الملف معظم مترجمي لغة C، لذلك سينجح هذا الأمر.

ومع ذلك، اعتمادًا على إعدادات ملفك أو مشروعك، قد يقوم ملف c المضمن بإنشاء ملف كائن منفصل. عند الارتباط، يمكن أن يؤدي ذلك إلى أحرف محددة مزدوجة.

اعتمادًا على بيئة البناء الخاصة بك (لن تحددها) قد تجد أنها تعمل بالطريقة التي تريدها تمامًا.

ومع ذلك، هناك العديد من البيئات (كل من IDEs والعديد من ملفات Makefiles المصنوعة يدويًا) التي تتوقع تجميع *.c - إذا حدث ذلك، فمن المحتمل أن تواجه أخطاء في الرابط بسبب الرموز المكررة.

بشكل عام، ينبغي تجنب هذه الممارسة.

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

يمكنك استخدام برنامج التحويل البرمجي gcc على نظام التشغيل Linux لربط ملفين بمخرج واحد. لنفترض أن لديك ملفين من نوع c، أحدهما هو "main.c" والآخر هو "support.c". لذا فإن الأمر لربط هذين هو

دول مجلس التعاون الخليجي main.c support.c -o main.out

سيتم ربط هذين الملفين بملف main.out واحد. لتشغيل الإخراج سيكون الأمر

./خارج الرئيسية

إذا كنت تستخدم وظيفة main.c التي تم الإعلان عنها في ملف support.c، فيجب عليك الإعلان عنها بشكل رئيسي أيضًا باستخدام فئة التخزين الخارجية.

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

لقد أتاح لنا تضمين ملفات ‎.c الفرصة للوصول إلى الترس الموجود في الجهاز، وهو ما كان مثيرًا للاهتمام بالنسبة لنا لاختباره.

لا تحظر لغة C هذا النوع من #include، ولكن يجب أن تظل وحدة الترجمة الناتجة صالحة لـ C.

لا أعرف ما هو البرنامج الذي تستخدمه مع الملف .prj. إذا كنت تستخدم شيئًا مثل "make" أو Visual Studio أو أي شيء آخر، فقط تأكد من تعيينه على قائمة الملفات التي تحتاج إلى تجميع بدون ملف لا يمكن تجميعه بشكل مستقل.

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

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

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

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

إذا قمت بوضع كل شيء في وحدة مصدر C واحدة، فستحصل على -

    تحسينات في الأداء وحجم التعليمات البرمجية - في العديد من الحالات، سيتم تضمين استدعاءات الوظائف. حتى بدون البطانة، يتمتع المترجم بالقدرة على إنتاج تعليمات برمجية أكثر كفاءة.

    يتم إخفاء مستوى القناة وبيانات الوظيفة.

    تجنب تلوث مساحة الاسم وعواقبه - يمكنك استخدام أسماء أقل تعقيدًا.

    تجميع واتصال أسرع.

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

ومع ذلك، تحتاج إلى فرض بعض الاتفاقيات للتعامل مع هذا. سيعتمد هذا إلى حد ما على سلسلة الأدوات الخاصة بك، ولكن بعض المؤشرات العامة هي كذلك

    ضع الواجهة العامة في ملف رأس منفصل - لا يزال يتعين عليك القيام بذلك.

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

    استخدم حراس المترجم لمنع تضمين الرؤوس الخاصة ووحدات المصدر بواسطة وحدات الترجمة الخارجية.

    يجب إعلان جميع البيانات والوظائف الشخصية ثابتة.

    الحفاظ على التمييز المفاهيمي بين ملفات .c و.h. يستخدم هذا الاتفاقيات الموجودة. الفرق هو أنه سيكون لديك الكثير من الإعلانات الثابتة في رؤوسك.

    إذا كانت سلسلة الأدوات الخاصة بك لا تفرض أي شيء، فلا ينبغي عليك تحديد ملفات التنفيذ الخاصة مثل .c و.h. إذا كنت تستخدم الحراس الممكّنين، فلن يقوموا بإنشاء تعليمات برمجية ولن يقدموا أي أسماء جديدة (قد ينتهي بك الأمر مع بعض المقاطع الفارغة نتيجة لذلك). الميزة الكبيرة هي أن الأدوات الأخرى (مثل IDEs) ستتعامل مع هذه الملفات وفقًا لذلك.

هذا جيد؟ نعم سوف تجميع

هل هذا موصى به؟ يتم تجميع ملفات no - .c في ملفات .obj، والتي يتم ربطها بعد التجميع (بواسطة الرابط) إلى ملف قابل للتنفيذ (أو مكتبة)، لذلك ليست هناك حاجة لتضمين ملف .c في ملف آخر. بدلاً من ذلك، ستحتاج على الأرجح إلى إنشاء ملف ‎.h يسرد الوظائف/المتغيرات المتوفرة في ملف ‎.c آخر، ويتضمن ملف ‎.h