वैसे, मैं इस बात से काफी हैरान हूं कि इस सिंटैक्स के विकल्पों का उल्लेख नहीं किया गया है। एक अन्य सामान्य (लेकिन पुराना) तंत्र एक फ़ंक्शन को कॉल करने के लिए है जो परिभाषित नहीं है और यदि आपका दावा सही है तो फ़ंक्शन कॉल को संकलित करने के लिए ऑप्टिमाइज़र पर भरोसा करें।
#define MY_COMPILETIME_ASSERT(test) \
do { \
extern void you_did_something_bad(void); \
if (!(test)) \
you_did_something_bad(void); \
} while (0)
हालांकि यह तंत्र काम करता है (जब तक अनुकूलन सक्षम होते हैं) इसमें लिंक न करने तक किसी त्रुटि की सूचना नहीं देने का नकारात्मक पक्ष है, जिस समय यह फ़ंक्शन के लिए परिभाषा खोजने में विफल रहता है you_did_something_bad ()। यही कारण है कि कर्नेल डेवलपर्स नकारात्मक आकार बिट फ़ील्ड चौड़ाई और नकारात्मक आकार सरणियों (बाद में जिनमें से जीसीसी 4.4 में ब्रेकिंग बिल्ड को रोक दिया) जैसी चाल का उपयोग करना शुरू कर दिया।
संकलन-समय की आवश्यकता के लिए सहानुभूति में, जीसीसी 4.3 ने error
फ़ंक्शन विशेषता को पेश किया जो आपको इस पुरानी अवधारणा पर विस्तार करने की अनुमति देता है, लेकिन आपके चयन के संदेश के साथ एक संकलन-समय त्रुटि उत्पन्न करता है - कोई और अधिक गुप्त "नकारात्मक" सरणी नहीं " त्रुटि संदेश!
#define MAKE_SURE_THIS_IS_FIVE(number) \
do { \
extern void this_isnt_five(void) __attribute__((error( \
"I asked for five and you gave me " #number))); \
if ((number) != 5) \
this_isnt_five(); \
} while (0)
वास्तव में, लिनक्स 3.9 के रूप में, अब हमारे पास एक मैक्रो है compiletime_assert
जो इस सुविधा का उपयोग करता है और अधिकांश मैक्रोज़ को bug.h
तदनुसार अपडेट किया गया है। फिर भी, इस मैक्रो का उपयोग इनिशियलाइज़र के रूप में नहीं किया जा सकता है। हालाँकि, स्टेटमेंट एक्सप्रेशन (एक और जीसीसी सी-एक्सटेंशन) का उपयोग करके , आप कर सकते हैं!
#define ANY_NUMBER_BUT_FIVE(number) \
({ \
typeof(number) n = (number); \
extern void this_number_is_five(void) __attribute__(( \
error("I told you not to give me a five!"))); \
if (n == 5) \
this_number_is_five(); \
n; \
})
यह मैक्रो ठीक एक बार इसके पैरामीटर का मूल्यांकन करेगा (यदि इसके साइड-इफेक्ट्स हैं) और एक संकलन-समय त्रुटि पैदा करता है जो कहता है "मैंने आपको पांच नहीं देने के लिए कहा था!" यदि अभिव्यक्ति पांच का मूल्यांकन करती है या संकलन-समय स्थिर नहीं है।
तो हम नकारात्मक-आकार वाले बिट-फ़ील्ड के बजाय इसका उपयोग क्यों नहीं कर रहे हैं? काश, वर्तमान में स्टेटमेंट एक्सप्रेशन के उपयोग के कई प्रतिबंध हैं, जिनमें निरंतर इनिशियलाइज़र के रूप में उनका उपयोग (एनम कांस्टेंट के लिए, बिट-फील्ड चौड़ाई, आदि) शामिल हैं, भले ही स्टेटमेंट एक्सप्रेशन पूरी तरह से स्थिर हो (यानी, पूरी तरह से मूल्यांकन किया जा सकता है) संकलन-समय पर और अन्यथा __builtin_constant_p()
परीक्षण पास करता है)। इसके अलावा, वे एक समारोह शरीर के बाहर इस्तेमाल नहीं किया जा सकता है।
उम्मीद है, जीसीसी जल्द ही इन कमियों में संशोधन करेगा और निरंतर बयान अभिव्यक्तियों को निरंतर शुरुआती के रूप में उपयोग करने की अनुमति देगा। यहाँ चुनौती भाषा विनिर्देश है जो एक कानूनी स्थिर अभिव्यक्ति है। C ++ 11 ने केवल इस प्रकार या चीज़ के लिए कॉन्स्ट्रेक्स कीवर्ड जोड़ा, लेकिन C11 में कोई भी प्रतिरूप मौजूद नहीं है। जबकि C11 को स्थैतिक अभिकथन मिला, जो इस समस्या का हिस्सा होगा, यह इन सभी कमियों को हल नहीं करेगा। इसलिए मुझे आशा है कि gcc एक विस्तार के रूप में एक constexpr कार्यक्षमता उपलब्ध कर सकता है -std = gnuc99 & -std = gnuc11 या कुछ इस तरह के और बयान अभिव्यक्ति एट पर इसके उपयोग की अनुमति देता है। अल।