C Language
अभिकथन
खोज…
परिचय
एक दावा एक विधेय है कि प्रस्तुत स्थिति उस समय सच होनी चाहिए जब सॉफ़्टवेयर द्वारा दावा किया जाता है। अधिकांश सामान्य सरल दावे हैं , जो निष्पादन के समय मान्य हैं। हालांकि, संकलन के समय स्थिर स्टेटमेंट की जाँच की जाती है।
वाक्य - विन्यास
- ज़ोर (अभिव्यक्ति)
- static_assert (अभिव्यक्ति, संदेश)
- _Static_assert (अभिव्यक्ति, संदेश)
पैरामीटर
पैरामीटर | विवरण |
---|---|
अभिव्यक्ति | अदिश प्रकार की अभिव्यक्ति। |
संदेश | नैदानिक संदेश में शामिल होने के लिए स्ट्रिंग शाब्दिक। |
टिप्पणियों
दोनों assert
और static_assert
में परिभाषित मैक्रो हैं assert.h
।
की परिभाषा assert
मैक्रो पर निर्भर करता है NDEBUG
जो मानक पुस्तकालय द्वारा परिभाषित नहीं है। यदि NDEBUG
परिभाषित किया गया है, assert
नो-सेशन है:
#ifdef NDEBUG # define assert(condition) ((void) 0) #else # define assert(condition) /* implementation defined */ #endif
राय इस बारे में भिन्न है कि क्या NDEBUG
उपयोग हमेशा उत्पादन संकलनों के लिए किया जाना चाहिए।
- समर्थक शिविर का तर्क है कि
assert
कॉलabort
और जोर संदेश अंत उपयोगकर्ताओं के लिए उपयोगी नहीं हैं, इसलिए परिणाम उपयोगकर्ता के लिए उपयोगी नहीं है। यदि आपके पास उत्पादन कोड में जांच करने के लिए घातक स्थितियां हैं, तो आपको साधारण का उपयोग करना चाहिएif/else
स्थिति और प्रोग्राम को समाप्त करने के लिएexit
याquick_exit
। के विपरीतabort
, इन कार्यक्रम कुछ सफाई करने के लिए (के साथ पंजीकृत कार्यों के माध्यम से की अनुमति देने केatexit
याat_quick_exit
)। - कॉन-कैंप का तर्क है कि
assert
कॉल को कभी भी उत्पादन कोड में आग नहीं लगानी चाहिए, लेकिन अगर वे करते हैं, तो जिस स्थिति की जांच की जाती है उसका मतलब है कि नाटकीय रूप से कुछ गलत है और यदि निष्पादन जारी रहता है तो कार्यक्रम खराब हो जाएगा। इसलिए, उत्पादन कोड में सक्रिय होना बेहतर है क्योंकि अगर वे आग लगाते हैं, तो नरक पहले से ही टूट गया है। - एक अन्य विकल्प मुखर प्रणाली का उपयोग करना है जो हमेशा चेक का प्रदर्शन करता है, लेकिन विकास (जहां
abort
उपयुक्त है) और उत्पादन (जहां एक 'अप्रत्याशित आंतरिक त्रुटि - कृपया तकनीकी सहायता से संपर्क करें' अधिक उपयुक्त हो सकता है) के बीच त्रुटियों को अलग तरीके से संभालें।
static_assert
विस्तार _Static_assert
जो एक कीवर्ड है। संकलित समय पर स्थिति की जाँच की जाती है, इस प्रकार condition
एक स्थिर अभिव्यक्ति होनी चाहिए। विकास और उत्पादन के बीच इसे अलग तरह से संभालने की आवश्यकता नहीं है।
पूर्वसर्ग और पदबंध
अभिकथन के लिए एक उपयोग का मामला पूर्व शर्त और पोस्टकंडिशन है। अनुबंध द्वारा अपरिवर्तनीय और डिजाइन बनाए रखने के लिए यह बहुत उपयोगी हो सकता है। एक उदाहरण के लिए एक लंबाई हमेशा शून्य या सकारात्मक होती है इसलिए इस फ़ंक्शन को शून्य या सकारात्मक मान वापस करना होगा।
#include <stdio.h>
/* Uncomment to disable `assert()` */
/* #define NDEBUG */
#include <assert.h>
int length2 (int *a, int count)
{
int i, result = 0;
/* Precondition: */
/* NULL is an invalid vector */
assert (a != NULL);
/* Number of dimensions can not be negative.*/
assert (count >= 0);
/* Calculation */
for (i = 0; i < count; ++i)
{
result = result + (a[i] * a[i]);
}
/* Postcondition: */
/* Resulting length can not be negative. */
assert (result >= 0);
return result;
}
#define COUNT 3
int main (void)
{
int a[COUNT] = {1, 2, 3};
int *b = NULL;
int r;
r = length2 (a, COUNT);
printf ("r = %i\n", r);
r = length2 (b, COUNT);
printf ("r = %i\n", r);
return 0;
}
सिंपल असेसमेंट
एक कथन एक कथन है जिसका उपयोग यह दावा करने के लिए किया जाता है कि कोड की उस रेखा तक पहुंचने पर एक तथ्य सही होना चाहिए। यह सुनिश्चित करने के लिए कि उपयोगी परिस्थितियाँ पूरी हो गई हैं जब किसी दावे को पारित करने की शर्त सच होती है, तो कोई कार्रवाई नहीं होती है। झूठी स्थितियों पर व्यवहार संकलक झंडे पर निर्भर करता है। जब कथनों को सक्षम किया जाता है, तो एक झूठा इनपुट तत्काल कार्यक्रम को रोक देता है। जब वे अक्षम होते हैं, तो कोई कार्रवाई नहीं की जाती है। आंतरिक और डिबग बिल्ड में अभिक्रियाओं को सक्षम करना और रिलीज़ बिल्ड में उन्हें अक्षम करना आम बात है, हालांकि अक्सर रिलीज़ में ही सक्षम किया जाता है। (चाहे समाप्ति बेहतर हो या त्रुटियों से बदतर हो, कार्यक्रम पर निर्भर करता है।) अभिक्रियाओं का उपयोग केवल आंतरिक प्रोग्रामिंग त्रुटियों को पकड़ने के लिए किया जाना चाहिए, जिसका अर्थ है आमतौर पर खराब पैरामीटर पारित किया जाना।
#include <stdio.h>
/* Uncomment to disable `assert()` */
/* #define NDEBUG */
#include <assert.h>
int main(void)
{
int x = -1;
assert(x >= 0);
printf("x = %d\n", x);
return 0;
}
NDEBUG
साथ संभावित उत्पादन अपरिभाषित:
a.out: main.c:9: main: Assertion `x >= 0' failed.
NDEBUG
साथ संभावित उत्पादन परिभाषित:
x = -1
NDEBUG
विश्व स्तर पर परिभाषित करने के लिए यह अच्छा अभ्यास है, ताकि आप अपने कोड को सभी NDEBUG
के साथ या साथ आसानी से संकलित कर सकें। ऐसा करने का एक आसान तरीका संकलक के विकल्प के रूप में NDEBUG
को परिभाषित करता है, या इसे एक साझा कॉन्फ़िगरेशन हेडर (जैसे config.h
) में परिभाषित करता है।
स्थैतिक अभिकथन
कोड संकलित होने पर स्थिति सही है या नहीं, यह जांचने के लिए स्टेटिक कथनों का उपयोग किया जाता है। यदि ऐसा नहीं है, तो संकलक को एक त्रुटि संदेश जारी करने और संकलन प्रक्रिया को रोकने की आवश्यकता होती है।
एक स्थिर कथन वह है जिसे संकलन समय पर जांचा जाता है, समय नहीं चलाया जाता है। हालत एक स्थिर अभिव्यक्ति होनी चाहिए, और यदि झूठी एक संकलक त्रुटि में परिणाम होगा। पहला तर्क, जाँच की गई स्थिति, एक स्थिर अभिव्यक्ति और दूसरी एक स्ट्रिंग शाब्दिक होनी चाहिए।
_Static_assert
विपरीत, _Static_assert
एक कीवर्ड है। एक सुविधा मैक्रो static_assert
<assert.h>
में परिभाषित किया गया है।
#include <assert.h>
enum {N = 5};
_Static_assert(N == 5, "N does not equal 5");
static_assert(N > 10, "N is not greater than 10"); /* compiler error */
C11 से पहले, स्थैतिक अभिकथन के लिए कोई प्रत्यक्ष समर्थन नहीं था। हालाँकि, C99 में, स्थैतिक दावे को मैक्रोज़ के साथ अनुकरण किया जा सकता है जो संकलन समय की स्थिति के गलत होने पर संकलन विफलता को ट्रिगर करेगा। _Static_assert
विपरीत, दूसरे पैरामीटर के लिए एक उचित टोकन नाम होना चाहिए ताकि इसके साथ एक चर नाम बनाया जा सके। यदि अभिकथन विफल हो जाता है, तो संकलक त्रुटि में चर नाम को देखा जाता है, क्योंकि उस चर का उपयोग एक वाक्यात्मक रूप से गलत सरणी घोषणा में किया गया था।
#define STATIC_MSG(msg, l) STATIC_MSG2(msg, l)
#define STATIC_MSG2(msg,l) on_line_##l##__##msg
#define STATIC_ASSERT(x, msg) extern char STATIC_MSG(msg, __LINE__) [(x)?1:-1]
enum { N = 5 };
STATIC_ASSERT(N == 5, N_must_equal_5);
STATIC_ASSERT(N > 5, N_must_be_greater_than_5); /* compile error */
C99 से पहले, आप किसी ब्लॉक में मनमाने स्थानों पर वैरिएबल की घोषणा नहीं कर सकते थे, इसलिए आपको इस मैक्रो का उपयोग करने के बारे में बेहद सतर्क रहना होगा, यह सुनिश्चित करते हुए कि यह केवल वही दिखाई देता है जहां एक चर घोषणा मान्य होगी।
अप्राप्य कोड का अभिकथन
विकास के दौरान, जब कुछ कोड पथों को नियंत्रण प्रवाह की पहुंच से रोका जाना चाहिए, तो आप यह बताने के लिए assert(0)
दे सकते हैं कि इस तरह की स्थिति गलत है:
switch (color) {
case COLOR_RED:
case COLOR_GREEN:
case COLOR_BLUE:
break;
default:
assert(0);
}
जब भी assert()
मैक्रो का तर्क गलत का मूल्यांकन करता है, तो मैक्रो नैदानिक जानकारी को मानक त्रुटि स्ट्रीम में लिख देगा और फिर प्रोग्राम को रद्द कर देगा। इस जानकारी में assert()
कथन की फ़ाइल और लाइन नंबर शामिल है और यह डीबगिंग में बहुत सहायक हो सकता है। मैक्रो NDEBUG
को परिभाषित करके NDEBUG
को निष्क्रिय किया जा सकता है।
किसी प्रोग्राम को समाप्त करने का दूसरा तरीका जब मानक लाइब्रेरी फ़ंक्शंस से exit
, quick_exit
या abort
। exit
और quick_exit
एक तर्क लें जो आपके पर्यावरण में वापस पारित किया जा सकता है। abort()
(और इस प्रकार assert
) आपके कार्यक्रम की एक बहुत गंभीर समाप्ति हो सकती है, और कुछ क्लीनअप्स जो अन्यथा निष्पादन के अंत में किए जाएंगे, प्रदर्शन नहीं किया जा सकता है।
assert()
का प्राथमिक लाभ यह है कि यह स्वचालित रूप से डिबगिंग जानकारी प्रिंट करता है। कॉलिंग abort()
का यह फायदा है कि इसे एसेस्टर की तरह डिसेबल नहीं किया जा सकता है, लेकिन इससे डिबगिंग की कोई भी जानकारी प्रदर्शित नहीं हो सकती है। कुछ स्थितियों में, दोनों निर्माणों का एक साथ उपयोग करना फायदेमंद हो सकता है:
if (color == COLOR_RED || color == COLOR_GREEN) {
...
} else if (color == COLOR_BLUE) {
...
} else {
assert(0), abort();
}
जब पाता सक्षम हैं, assert()
कॉल डिबग जानकारी प्रिंट और कार्यक्रम समाप्त कर देगा। निष्पादन कभी भी abort()
कॉल तक नहीं पहुंचता है। जब मुखर अक्षम होते हैं , assert()
कॉल कुछ नहीं करता है और abort()
कहा जाता है। यह सुनिश्चित करता है कि कार्यक्रम हमेशा इस त्रुटि स्थिति के लिए समाप्त होता है; डीबग आउटपुट प्रिंट किया गया है या नहीं, केवल यह सुनिश्चित करने और सक्षम करने से प्रभाव पड़ता है।
आपको उत्पादन कोड में इस तरह के assert
को कभी नहीं छोड़ना चाहिए, क्योंकि डिबग की जानकारी अंतिम उपयोगकर्ताओं के लिए सहायक नहीं है और क्योंकि abort
आम तौर पर बहुत अधिक गंभीर समाप्ति है जो क्लीनअप हैंडलर को बाधित करता है जो exit
लिए स्थापित होते हैं या चलाने के लिए quick_exit
।
त्रुटि संदेश दर्ज करें
एक चाल मौजूद है जो एक जोर के साथ त्रुटि संदेश प्रदर्शित कर सकती है। आम तौर पर, आप इस तरह कोड लिखेंगे
void f(void *p)
{
assert(p != NULL);
/* more code */
}
यदि दावा विफल हो गया, तो एक त्रुटि संदेश जैसा होगा
दावा विफल: p! = NULL, फ़ाइल main.c, पंक्ति 5
हालाँकि, आप एक त्रुटि संदेश देने के लिए तार्किक और ( &&
) का उपयोग कर सकते हैं
void f(void *p)
{
assert(p != NULL && "function f: p cannot be NULL");
/* more code */
}
अब, यदि अभिकथन विफल हो जाता है, तो एक त्रुटि संदेश कुछ इस तरह से पढ़ेगा
दावा विफल: p! = NULL && "फ़ंक्शन f: p को NULL नहीं किया जा सकता", फ़ाइल main.c, पंक्ति 5
यह कार्य करने का कारण यह है कि एक स्ट्रिंग शाब्दिक हमेशा गैर-शून्य (सत्य) का मूल्यांकन करता है। बूलियन अभिव्यक्ति में && 1
जोड़ने का कोई प्रभाव नहीं होता है। इस प्रकार, && "error message"
जोड़ने से कोई प्रभाव नहीं पड़ता है, सिवाय इसके कि संकलक संपूर्ण अभिव्यक्ति प्रदर्शित करेगा जो विफल हो गया।