2012-03-14 13 views
7
00001 /* assert.h 
00002 Copyright (C) 2001, 2003 Free Software Foundation, Inc. 
00003 Written by Stephane Carrez ([email protected])  
00004 
00005 This file is free software; you can redistribute it and/or modify it 
00006 under the terms of the GNU General Public License as published by the 
00007 Free Software Foundation; either version 2, or (at your option) any 
00008 later version. 
00009 
00010 In addition to the permissions in the GNU General Public License, the 
00011 Free Software Foundation gives you unlimited permission to link the 
00012 compiled version of this file with other programs, and to distribute 
00013 those programs without any restriction coming from the use of this 
00014 file. (The General Public License restrictions do apply in other 
00015 respects; for example, they cover modification of the file, and 
00016 distribution when not linked into another program.) 
00017 
00018 This file is distributed in the hope that it will be useful, but 
00019 WITHOUT ANY WARRANTY; without even the implied warranty of 
00020 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
00021 General Public License for more details. 
00022 
00023 You should have received a copy of the GNU General Public License 
00024 along with this program; see the file COPYING. If not, write to 
00025 the Free Software Foundation, 59 Temple Place - Suite 330, 
00026 Boston, MA 02111-1307, USA. */ 
00027 
00028 #ifndef _ASSERT_H 
00029 #define _ASSERT_H 
00030 
00031 #ifdef NDEBUG 
00032 # define assert(EX) 
00033 #else 
00034 # define assert(EX) (void)((EX) || (__assert (#EX, __FILE__, __LINE__),0)) 
00035 #endif 
00036 
00037 #ifdef __cplusplus 
00038 extern "C" { 
00039 #endif 
00040 
00041 extern void __assert (const char *msg, const char *file, int line); 
00042 
00043 #ifdef __cplusplus 
00044 }; 
00045 #endif 
00046 #endif 

प्रश्न यह है: लाइन 34 पर "(शून्य)" के लिए क्या है और __assert क्या है?सी ++ assert.h

उत्तर

11

देखो:

extern void __assert (const char *msg, const char *file, int line); 

__assert समारोह है कि एक अभिकथन संदेश, फ़ाइल नाम और तर्क के रूप में एक लाइन नंबर लेता है। असल में, यह वह तरीका है जो त्रुटि संदेश को प्रिंट करता है और जब दावा विफल होता है तो प्रोग्राम को समाप्त कर देता है।

#define assert(EX) (void)((EX) || (__assert (#EX, __FILE__, __LINE__),0)) 

यह assert(EX) मैक्रो हां, तो यह पहले की जाँच करता पूर्व अभिव्यक्ति और परिभाषित करता है (क्योंकि सी ++ || ऑपरेटर के शॉर्ट सर्किट आपरेशन के) केवल यह है:

फिर ऊपर मैक्रो परिभाषा को देखो विफल रहता है, यह __assert फ़ंक्शन को कॉल करता है और एक स्ट्रिंग के रूप में असफल दावा अपवाद को पास करता है, और आपकी स्रोत फ़ाइलों में assert() विधि कॉल का सटीक स्थान। इस पूर्वप्रक्रमक प्रवंचना के साथ जोर पुस्तकालय कि जब आप अपने प्रोग्राम में निम्न लिखें

assert(a == 0); 

और अपने दावे के कार्यक्रम चलाने के दौरान विफल रहता है, आप विस्तृत

Assertion failed: a == 0 at program.c, line 23 

त्रुटि संदेश है कि आप में मदद करता है पाने को प्राप्त होता है उस सटीक स्थान की पहचान करें जहां आपके कोड में दावा विफल रहा था।

(void) भाग सिर्फ यह सुनिश्चित करने के लिए है कि संकलक (EX) || 0 अभिव्यक्ति के अप्रयुक्त परिणाम के बारे में कुछ चेतावनियां नहीं रखेगा, अन्य उत्तरों देखें, लोगों ने इसे अच्छी तरह समझाया।

शेष प्रीप्रोसेसर परिभाषित NDEBUG का उपयोग सभी संकलन समय पर दावा उत्पादन को चालू करने के लिए किया जाता है, आप परिणामी निष्पादन योग्य छोटे और तेज़ होंगे।

+0

विस्तृत स्पष्टीकरण के लिए सभी सही, सही, धन्यवाद के रूप में मैक्रो लिख सकते हैं। केवल दो प्रश्न: 1) क्यों (__assert (#EX, __FILE__, __LINE __), 0) इसका उपयोग ", 0" और 2) किया जाता है) क्यों (क्या तंत्र) कंपाइलर की चेतावनी को दबा देता है जब आप शून्य को शून्य में डाल देते हैं? क्या ऐसा इसलिए है क्योंकि शून्य कुछ भी नहीं है ??? – Narek

+4

1) [अल्पविराम ऑपरेटर] (http://en.wikipedia.org/wiki/Comma_operator) (',') पहले अपने बाएं ('__assert' कॉल) पर अभिव्यक्ति निष्पादित करता है, फिर उसके दाईं ओर (शाब्दिक' 0') और बाद वाले के परिणाम देता है। इसकी आवश्यकता है क्योंकि '||' ऑपरेटर को बुलियन-संगत ऑपरेंड की अपेक्षा है, लेकिन '__assert' फ़ंक्शन' शून्य 'देता है। – buc

+4

2) एक बयान की कल्पना करें '(ए == 3) || (0); एक पंक्ति पर अकेले। यह तुलना करने के लिए ज्यादा समझ में नहीं आता है और फिर परिणाम के साथ कुछ भी नहीं करता है। संकलक यह भी पहचानता है और संदेह करता है कि आप कथन पूरा करने के लिए भूल गए हैं और आपको इसके बारे में चेतावनी देते हैं। पूरी अभिव्यक्ति को 'शून्य' पर कास्ट करके: '(शून्य) ((ए == 3) || (0))' आप संकलक को बताते हैं कि इस अभिव्यक्ति के पास कोई समझदार परिणाम मान नहीं है (जैसे 'शून्य' रिटर्निंग फ़ंक्शन भी नहीं होगा), इसलिए यह इसके बारे में शिकायत नहीं करेगा। – buc

1

यह अप्रयुक्त मूल्यों या चर के बारे में संकलक चेतावनियों को दबाता है।

दाईं तरफ कॉमा ऑपरेटर को भी ध्यान दें, जो || दोनों पक्षों को बूल में परिवर्तित करने के लिए बनाता है।

__assert एक आंतरिक कार्य है जो संभावित रूप से एक संदेश मुद्रित करेगा और आवश्यक दावा व्यवहार लागू करेगा (यानी abort() पर कॉल करें)।

7

__assert कार्यान्वयन का हिस्सा है; इस मामले में, पुस्तकालय में एक समारोह जिसे दावा विफलता के मामले में बुलाया जाएगा। और (void)|| ऑपरेटर के अप्रयुक्त परिणामों के बारे में संकलक चेतावनियां बंद करने के लिए बस है। इस लाइन az

1

लगभग ...

पर विचार करें: assert(a == 0); यह

(void)((a == 0) || (__assert (#a == 0, __FILE__, __LINE__),0))

करने के लिए विस्तारित किया गया है आप अभिव्यक्ति (x || y) है - इस मामले में दोनों x और y, bools के रूप में मूल्यांकन इसलिए यदि 'एक' 0 evals, परिभाषा का || अगले बूल लाइन में कोशिश करने के लिए कहते हैं, यानी 'वाई'

तो - यदि आपका दावा गलत है, (__assert (#a == 0, __FILE__, __LINE__),0) का मूल्यांकन किया जाता है, जिसका अर्थ है __assert() कॉल किया जाता है।

क्यों (__assert(), 0) ?? __assert void __assert() के रूप में परिभाषित एक फ़ंक्शन है - ठीक है ... अधिकांश समय। assert() मैक्रोज़ के एक सेट के लिए http://www.opensource.apple.com/source/Libc/Libc-825.26/include/assert.h देखें - ध्यान दें कि उनमें से सभी एक फ़ंक्शन को कॉल करते हैं ...

कॉमा ऑपरेटर आपको एक ही कथन में दो चीजें करने देता है, यानी i++, j++ - लेकिन एक अभिव्यक्ति को याद रखना है का मूल्यांकन कुछ मूल्य - इस मामले में "0" पर - इसलिए पूरा कथन (void)(0 || 0) का मूल्यांकन करता है जो वैध अभिव्यक्ति है। एक दुष्प्रभाव के रूप में, आपकी अभिव्यक्ति का मूल्यांकन किया जाता है और संभवतः एक समारोह को बुलाया जाता है।

(void)(0 || 0) में नोट पहले 0 आपके असफल दावे से है। यह संकलन समय पर बनाया जा सकता है यदि आपका दावा किसी स्थिरता के रूप में बना सकता है, या एक अभिव्यक्ति जिसे मूल्यांकन किया जाता है, यानी (void)((a == 0) || 0)

नोट करें कि अल्पविराम "0" वास्तव में पैडेंटिक कंपाइलर्स के लिए है - मैं आमतौर पर डॉन करता हूं इसे नहीं देख रहा हूँ। लेकिन (a || __assert()) बहुत आम है। आप

#define assert(x) { if(! (x)) __assert(.....); }