Table of Contents

पोर्टेबल सी कोड लेखन पेशेवर सॉफ्टवेयर इंजीनियरिंग का एक आधारशिला है, जो अनुप्रयोगों को विभिन्न हार्डवेयर आर्किटेक्चर, ऑपरेटिंग सिस्टम और कम से कम काम के साथ कम्पाइलर को चलाने में सक्षम बनाता है। पोर्टेबिलिटी रखरखाव ओवरहेड को कम करती है, उपयोगकर्ता आधार को व्यापक करती है, और विकसित प्लेटफार्मों के खिलाफ भविष्य के सबूत कोड को बढ़ाती है। यह लेख वास्तविक पोर्टेबिलिटी को प्राप्त करने के लिए युद्ध-परीक्षण सर्वोत्तम प्रथाओं को रोकता है, जो सी मानक और वास्तविक दुनिया के अनुभव के दशकों में आधारित है।

मंच मतभेदों को समझना

पोर्टेबिलिटी तकनीकों को लागू करने से पहले, डेवलपर्स को प्लेटफार्मों के बीच मौजूद भिन्नता के प्रकारों को पहचानना चाहिए। ये अंतर चार व्यापक श्रेणियां हैं: कम्पाइलर व्यवहार, ऑपरेटिंग सिस्टम एपीआई, हार्डवेयर वास्तुकला और संसाधन बाधाएं।

Compiler Variations

C compilers - GCC, Clang, और MSVC से एम्बेडेड उपकरण जैसे IAR और Keil - C मानक को अनुरूपता के विभिन्न स्तरों के साथ लागू करें। वे ] हस्ताक्षर, बिट-फील्ड लेआउट, संरचना पैडिंग, और या के सटीक अर्थों में भिन्न हो सकते हैं। भाषा विस्तार (जैसे, GNU C एक्सटेंशन, Microsoft's ))) भी छिपा निर्भरता पैदा कर सकते हैं।

ऑपरेटिंग सिस्टम अंतर

POSIX-like सिस्टम (Linux, MacOS, BSD) कई एपीआई साझा करते हैं, लेकिन विंडोज सिस्टम कॉल के मूल रूप से अलग सेट को उजागर करता है। फ़ाइल I/O, थ्रेडिंग, डायनेमिक लिंकिंग, सिग्नल और प्रक्रिया नियंत्रण को अक्सर सशर्त संकलन या अमूर्त परत की आवश्यकता होती है। यहां तक कि फ़ाइल नाम केस संवेदनशीलता और पथ विभाजक (बैकस्लैश बनाम फॉरवर्ड स्लैश) को देखभाल की आवश्यकता होती है।

हार्डवेयर वास्तुकला और एंडियानेस

प्रोसेसर शब्द आकार (32-bit बनाम 64-bit) में भिन्न होते हैं, बाइट ऑर्डर (बिग-एंड्रियन या छोटे-endian), संरेखण आवश्यकताओं और निर्देश सेट सुविधाओं। कोड जो मान लेता है 32 बिट है या एक सूचक एक में फिट बैठता है कई प्लेटफार्मों पर विफल हो जाएगा। नेटवर्क हस्तांतरण या फ़ाइल भंडारण के लिए डेटा को क्रमबद्ध करते समय एंडियननेस महत्वपूर्ण हो जाती है।

संसाधन रोकथाम

एम्बेडेड सिस्टम या गहराई से एम्बेडेड लक्ष्य एक ऑपरेटिंग सिस्टम की कमी हो सकती है, इसमें सीमित स्टैक / ढेर आकार होते हैं, और ] को प्रतिबंधित प्रारूप specifiers के साथ कार्यान्वयन प्रदान करते हैं। पोर्टेबल कोड को स्मृति उपलब्धता और रनटाइम समर्थन के बारे में धारणाओं से बचना चाहिए।

पोर्टेबल सी कोड के लिए कोर बेस्ट प्रैक्टिस

स्टैंडर्ड सी पुस्तकालयों पर निर्भर

C मानक पुस्तकालय (ISO/IEC 9899) एक आधार रेखा प्रदान करता है जो प्रत्येक अनुरूपण कम्पाइलर को आपूर्ति करनी चाहिए। , ], , और ]]] जैसे कार्य प्लेटफार्मों पर समान रूप से व्यवहार करते हैं। [[FLT: 11] (POSIX) जैसे प्लेटफॉर्म-विशिष्ट समकक्षों से बचें, जब तक [[FLT: 12]]]]] द्वारा संरक्षित नहीं किया गया। गणितीय संचालन के लिए, [[FLT: 13]]] को विक्रेता-विशिष्ट वेक्टर पुस्तकालयों पर पसंद करते हैं।

फिक्स्ड-वाइडे इंटीगर टाइप का उपयोग करें

] हेडर ], , और ]] जैसे प्रकारों को परिभाषित करता है जो सटीक आकार की गारंटी देता है। हमेशा उन्हें जब मूल्यों के मामले की सीमा - उदाहरण के लिए, जब प्रोटोकॉल बफर या हार्डवेयर रजिस्टर को परिभाषित किया जाता है। इसी तरह, प्रारूप specifiers (]]]]] का उपयोग करें, ]]]) इन प्रकार को पोर्टेबल रूप से मुद्रित करने के लिए।

#include <stdint.h>
#include <inttypes.h>
int32_t val = -100;
printf("Value: %" PRId32 "\n", val);

मौलिक प्रकार के बारे में धारणाओं से बचें

कभी नहीं मान लें कि 32 बिट्स है, 64 बिट्स है, या ] पर हस्ताक्षर किए गए हैं। ] और ]] स्थिरांक (]]], ]]]]]]]]] का प्रयोग करें। सूचकों के लिए, या ] का उपयोग करें यदि आपको उन्हें पूर्णांक के रूप में स्टोर करना होगा।

एंडियननेस को स्पष्ट रूप से संभालना

जब मशीनों (नेटवर्क, फ़ाइल, या साझा मेमोरी) में द्विआधारी डेटा का आदान-प्रदान होता है, तो हमेशा एक ज्ञात बाइट ऑर्डर में परिवर्तित होते हैं - पारंपरिक नेटवर्क बाइट ऑर्डर (बिग-एंडियन)। POSIX कार्यों [[FLT: 31]]], [[FLT: 32]], [[FLT: 34]]]], [[FLT:]]]]], [[FLT: 34]]]]] व्यापक रूप से उपलब्ध हैं; गैर-POSIX सिस्टम के लिए, [[FLT: 35] और रनटाइम डिटेक्शन का उपयोग करके अपना खुद का कार्यान्वयन प्रदान करें।

सार फ़ाइल सिस्टम संचालन

फ़ाइल पथ सीमक भिन्न (]] यूनिक्स पर ]]]] विंडोज़ पर भिन्न होते हैं। मैक्रो या एक छोटी उपयोगिता फ़ंक्शन का उपयोग करें जो पथ को सामान्य करता है। निर्देशिका पुनरावृत्ति के लिए, POSIX एपीआई मानक है; विंडोज पर आप उसी इंटरफेस के पीछे लपेट सकते हैं। हार्ड कोडिंग पूर्ण पथ से बचें।

Undefed and कार्यान्वयन-परिभाषित Behaviour

C मानक कई कार्यों को अपरिभाषित या कार्यान्वयन-परिभाषित रूप में नामित करता है। उदाहरणों में हस्ताक्षरित पूर्णांक अतिप्रवाह शामिल है, जो प्रकार की चौड़ाई से अधिक तक स्थानांतरित हो जाता है, और मूल्यांकन ]। स्थैतिक विश्लेषकों का उपयोग करें जैसे Cppcheck या ]Clang-Tidy] ऐसे पैटर्न को पकड़ने के लिए, और कोड लिखने के लिए जो सख्ती से अनुरूप है।

Compile-Time चयन के लिए उत्तोलन Preprocessor Macros

सशर्त संकलन मंच विशिष्ट कोड के लिए आवश्यक है, लेकिन दुरुपयोग एक उलझन वाली गड़बड़ बना सकता है। अच्छी तरह से ज्ञात पूर्व-परिभाषित मैक्रोज़ का उपयोग करें: , ], , ], और कम्पाइलर मैक्रोज़ जैसे ] हमेशा प्रत्येक दस्तावेज़ ] शाखा और मंच विशिष्ट वर्गों को छोटा रखें।

#ifdef _WIN32
 #include <windows.h>
 #define SLEEP(ms) Sleep(ms)
#else
 #include <unistd.h>
 #define SLEEP(ms) usleep((ms)*1000)
#endif

सिस्टम कॉल के लिए संयम परत का उपयोग करें

थ्रेडिंग, सॉकेट, टाइमर और मेमोरी प्रबंधन के लिए, पतली रैपर बनाते हैं। उदाहरण के लिए, एक प्रकार और फ़ंक्शन को परिभाषित करें जो यूनिक्स पर POSIX धागे के मानचित्र और ]] पर Windows। एक ही दृष्टिकोण गतिशील पुस्तकालयों (] बनाम ]]) के लिए काम करता है। कई ओपन सोर्स पुस्तकालयों (जैसे, ]plibc], Apache APR) पहले से ही इस तरह के सार प्रदान करते हैं।

एकाधिक प्लेटफार्मों पर टेस्ट प्रारंभिक और अक्सर

सतत एकीकरण (सीआई) पाइपलाइनों को लिनक्स, मैकओएस, विंडोज और किसी भी एम्बेडेड लक्ष्य पर परीक्षण सूट को संकलित और चलाने चाहिए। तैनाती से पहले आर्किटेक्चर-विशिष्ट बग को पकड़ने के लिए क्रॉस-कंपाइलर और एमुलेटर (जैसे QEMU) का उपयोग करें। ctest[[FLT1]] या Cमेक/CTest]]] जैसे उपकरणों के साथ स्वचालित परीक्षण पोर्टेबिलिटी को लागू करने में मदद करता है।

उन्नत पोर्टेबिलिटी तकनीक

Cमेक या ऑटोटूल के साथ सिस्टम कॉन्फ़िगरेशन का निर्माण

आधुनिक निर्माण प्रणाली कॉन्फ़िगर समय पर मंच विशेषताओं का पता लगा सकती है। Cमेक , , और मॉड्यूल एक उत्पन्न करते हैं] कि आपका कोड शामिल हो सकता है। यह ब्रिटल ] श्रृंखलाओं को एक ही बिंदु के साथ बदल देता है।

// Generated config.h
#define HAVE_STDINT_H 1
#define WORDS_BIGENDIAN 0
#define SIZEOF_LONG 8

पोर्टेबल इनलाइन असेंबली और इंट्रिनिक्स

जब प्रदर्शन की मांग मंच विशिष्ट निर्देश (जैसे, SIMD, CPUID), उन्हें अलग फ़ाइलों में encapsulate और निर्माण के दौरान सही फ़ाइल का चयन करें। इनलाइन असेंबली के बजाय GCC/Clang/ICC/VS से compiler intrinsics (जैसे ] का उपयोग करें, क्योंकि इन्टरिनिक्स एक ही वास्तुकला पर कम्पाइलर के पार अधिक पोर्टेबल हैं।

डेटा संरचनाएं स्पष्ट रूप से संरेखित

संरचना पैकिंग और संरेखण भिन्न होता है। संरेखण को लागू करने के लिए C11 (]] से निर्दिष्ट करें। पुराने कम्पाइलर के लिए, पूर्व प्रसंस्करणकर्ता-आधारित वर्कअराउंड (] को GCC के लिए रोजगार दें, MSVC के लिए]]]।

सिग्नल हैंडलिंग संगतता

सिग्नल स्थिरांक (], ) और सुरक्षित सिग्नल हैंडलिंग व्यापक रूप से भिन्न होते हैं। POSIX एपीआई पुराने के लिए बेहतर है। विंडोज पर, संकेत कंसोल नियंत्रण हैंडलर्स के माध्यम से अनुकरण किए जाते हैं। आश्चर्य से बचने के लिए एक आम समारोह के पीछे संकेत पंजीकरण।

कैसे बचें

पर निर्भर करता है एक Fallback के बिना

] POSIX पर मानक है लेकिन कई एम्बेडेड प्लेटफार्मों और पुराने Windows परिवेश पर लापता है। plibc] जैसे पोर्टेबल कार्यान्वयन का उपयोग करें या एक न्यूनतम ] को बंडल करें।

] का आकलन एक हस्ताक्षरित पूर्णांक है

C मानक केवल कहते हैं एक वास्तविक प्रकार का प्रतिनिधित्व करने में सक्षम है समय। कुछ एम्बेडेड सिस्टम पर यह एक असाइन किए गए 32-bit मान है; दूसरों पर यह 64-bit हस्ताक्षरित पूर्णांक है। इसके गुणों की जांच किए बिना ] पर कभी भी अंकगणित नहीं किया जाता है, या ] का उपयोग किया जाता है।

सिस्टम कॉल में थ्रेड सुरक्षा को निग्ले करना

], ], और ]] जैसे कार्य स्थिर बफर का उपयोग करते हैं और थ्रेड-सुरक्षित नहीं हैं। पुनर्वित्त वेरिएंट (]], ]]]]] का प्रयोग करें जहां संभव हो, और उन प्लेटफार्मों पर फ्लेमबैक कार्यान्वयन प्रदान करते हैं जिनकी कमी उनके पास है।

निष्कर्ष

पोर्टेबल सी कोड लेखन एक अनुशासन और एक निवेश दोनों है। सी मानक के करीब से चिपके हुए, फिक्स्ड-विड्थ प्रकार, अमूर्त प्रणाली इंटरफेस का चयन और कई प्लेटफार्मों पर परीक्षण करके, डेवलपर्स सॉफ्टवेयर का उत्पादन कर सकते हैं जो सुपर कंप्यूटर से माइक्रोकंट्रोलर तक के वातावरण में विश्वसनीय रूप से चलता है। प्रथाओं में यहां रेखांकित किया गया है - आधुनिक निर्माण प्रणाली विन्यास और स्थैतिक विश्लेषण के साथ संयुक्त - क्रॉस-प्लेटफॉर्म सी विकास के लिए एक टिकाऊ आधार बनाती है। याद रखें: पोर्टेबिलिटी एक बाद में नहीं है; यह एक डिज़ाइन लक्ष्य है जो परियोजना के जीवन चक्र के दौरान लाभांश का भुगतान करता है।