2009-10-16 9 views
10

हमारे स्थिर विश्लेषण उपकरण एक "वापसी प्रकार पर बेकार प्रकार क्वालीफायर" के बारे में शिकायत हम इस तरह के रूप में हेडर फाइल में प्रोटोटाइप है जब:स्पष्टता के लिए वापसी प्रकारों पर बेकार प्रकार क्वालीफायर का उपयोग किया जाना चाहिए?

const int foo(); 

हम इसे इस तरह से परिभाषित क्योंकि समारोह एक निरंतर कि कभी नहीं होगा परिवर्तन लौट रहा है , यह सोचकर कि एपीआई const जगह के साथ स्पष्ट लग रहा था।

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

मेरा सवाल है, क्या कोई कारण है कि इससे कोई समस्या हो सकती है? क्या हमें उपकरण द्वारा उत्पन्न त्रुटियों को अनदेखा करना चाहिए, या क्या हमें कम स्पष्ट और सुसंगत एपीआई की संभावित लागत पर उपकरण को शांत करना चाहिए? (यह अन्य const char* स्थिरांक देता है जिसमें उपकरण में कोई समस्या नहीं है।)

उत्तर

25

आमतौर पर आपके कोड के लिए जितना संभव हो सके सटीक वर्णन करने के लिए बेहतर होता है। आपको यह चेतावनी मिल रही है क्योंकि constconst int foo(); मूल रूप से अर्थहीन है। एपीआई केवल स्पष्ट दिखता है अगर आपको नहीं पता कि const कीवर्ड का अर्थ क्या है। इस तरह का अर्थ अधिभारित न करें; static जितना खराब है उतना खराब है, और अधिक भ्रम की संभावना जोड़ने का कोई कारण नहीं है।

const char * का अर्थ है const int से कुछ अलग है, यही कारण है कि आपका टूल इसके बारे में शिकायत नहीं करता है। पूर्व एक स्थिर स्ट्रिंग के लिए एक सूचक है, जिसका अर्थ है कि उस प्रकार को वापस करने वाले फ़ंक्शन को कॉल करने वाले किसी भी कोड को स्ट्रिंग की सामग्री को संशोधित करने का प्रयास नहीं करना चाहिए (यह उदाहरण के लिए रोम में हो सकता है)। बाद के मामले में, सिस्टम को यह लागू करने का कोई तरीका नहीं है कि आप int पर परिवर्तन नहीं करते हैं, इसलिए क्वालीफायर व्यर्थ है। वापसी प्रकार के लिए करीब से समानांतर होगा:

const int foo(); 
char * const foo2(); 

जो दोनों के कारण अपने स्थिर विश्लेषण चेतावनी देने के लिए होगा - एक रिटर्न मान पर एक स्थिरांक क्वालीफायर जोड़ने एक अर्थहीन ऑपरेशन है। यह केवल तब समझ में आता है जब आपके पास संदर्भ पैरामीटर (या वापसी प्रकार) होता है, जैसे आपके const char * उदाहरण।

वास्तव में, मैं सिर्फ एक छोटे से परीक्षण कार्यक्रम बनाया है, और जीसीसी भी स्पष्ट रूप से इस समस्या के बारे में चेताते:

test.c:6: warning: type qualifiers ignored on function return type 

तो यह सिर्फ अपने स्थिर विश्लेषण कार्यक्रम है कि शिकायत नहीं है।

+3

सहमत हुए। एक कॉन्स रिटर्न प्रकार पर मेरी तत्काल प्रतिक्रिया यह मानना ​​है कि वापसी एक साझा बफर को संदर्भ/सूचक है जिसे बदला नहीं जाना चाहिए। मेरा मानसिक मॉडल यह है कि कॉन्स कंटेनर पर लागू होता है (उदा। चर), सामग्री नहीं। उदाहरण के लिए "कॉन्स char *" में, कॉन्स पॉइंट-टू स्ट्रिंग पर लागू होता है, जबकि यदि आपके पास "const int i = 5" है, तो आप अभी भी अभिव्यक्ति में "i + 1" लिख सकते हैं - आप इसके साथ काम कर सकते हैं जब तक आप चर बदलने की कोशिश नहीं करते हैं तब तक मूल्य। एक साधारण int वापसी के साथ, आपके पास वास्तव में एक कंटेनर नहीं है - केवल एक मान। – Steve314

+0

मुझे लगता है कि लोग 'const' कीवर्ड के अजीब व्यवहार के कारण भ्रमित हो जाते हैं। मेरा मतलब है कि 'कॉन्स char * c' और' char const * c' एक ही चीज़ हैं। यदि पूर्व वाक्यविन्यास कानूनी नहीं थे, तो चीजें बहुत कम उलझन में होंगी। हमारे पास केवल 'char const * c' और 'char * const c' होगा और सभी को पता चलेगा कि क्या हो रहा है। शायद मैं इसके बारे में बहुत सोच रहा हूँ। –

+0

ठीक है, मुझे विश्वास है। जीसीसी चेतावनी को इंगित करने के लिए धन्यवाद। मेरी इच्छा है कि यह चेतावनी के बजाय एक त्रुटि होगी, इसलिए इस तरह के ग्रे क्षेत्र नहीं आते हैं। – mpontillo

4

आप उपकरण को नाखुश किए बिना अपने इरादे को चित्रित करने के लिए एक अलग तकनीक का उपयोग कर सकते हैं।

#define CONST_RETURN 

CONST_RETURN int foo(); 

आप क्योंकि है कि लगातार वर्ण, नहीं एक निरंतर सूचक के लिए सूचक की घोषणा है const char * के साथ एक समस्या नहीं है।

+3

लेकिन यह देखते हुए कि CONST_RETURN दावे की कोई कंपाइलर जांच नहीं है, क्या कोई टिप्पणी करना बेहतर नहीं है? इस तरह, कम से कम यह * देखो * जैसा कि संकलक ने जांच की हो। – Steve314

+0

हां, एक टिप्पणी भी बेहतर हो सकती है। –

+0

कुछ एपीआई/पुस्तकालय मैंने देखा है जिन्होंने इस तरह कुछ किया है। यदि आपके पास कोई ऐसा फ़ंक्शन है जो हमेशा एक ही नंबर देता है, तो '# परिभाषित करें foo() VALUE' चाल हो सकती है। –

3

const int foo()const char* foo() से बहुत अलग है। const char* foo() एक सरणी (आमतौर पर एक स्ट्रिंग) देता है जिसकी सामग्री को बदलने की अनुमति नहीं है।के बीच अंतर के बारे में सोचो:

const char* a = "Hello World"; 

और

const int b = 1; 

a अभी भी एक चर रहा है और अन्य तार कि जबकि b नहीं बदल सकते हैं को सौंपा जा सकता एक चर नहीं है। तो

const char* foo(); 
const char* a = "Hello World\n"; 
a = foo(); 

की अनुमति है लेकिन

const int bar(); 
const int b = 0; 
b = bar(); 

की अनुमति नहीं है यहां तक ​​कि bar() की const घोषणा के साथ।

+2

'const int b = bar() 'की अनुमति है, क्योंकि आप हमेशा' const' चर प्रारंभ कर सकते हैं। क्या आपका मतलब है 'const int b; बी = बार() '? –

+0

आप सही हैं। उत्तर सही किया गया। – atlpeg

4

अब const को अनदेखा कर रहा है, foo() एक मान देता है। आप

int x = foo(); 

करते हैं और मूल्य चर x को foo() द्वारा दिया, ठीक वैसे ही आप

int x = 42; 

को चर x मूल्य 42 आवंटित करने के लिए क्या कर सकते हैं प्रदान कर सकते हैं।
लेकिन आप 42 ... या foo() द्वारा लौटाए गए मूल्य को नहीं बदल सकते हैं। foo()foo() के प्रकार के लिए const कीवर्ड को लागू करके foo() से लौटाया गया मूल्य बदला नहीं जा सकता है।

मानconst (या restrict, या volatile) नहीं हो सकता। केवल वस्तुओं के प्रकार क्वालीफायर हो सकते हैं।

const char *foo(); 

इस मामले में साथ


कंट्रास्ट, foo() एक वस्तु के लिए सूचक देता है। लौटाए गए मूल्य से इंगित ऑब्जेक्ट const योग्यता प्राप्त किया जा सकता है।

3

int प्रति द्वारा वापस किया गया है। यह एक कॉन्स की एक प्रति हो सकती है, लेकिन जब इसे किसी और चीज़ के लिए सौंपा गया है, तो इस तथ्य के आधार पर कि यह असाइन करने योग्य था, परिभाषा द्वारा परिभाषा नहीं हो सकती है।

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

+0

कॉन्स int पीआई = 3.1415 9 क्या करता है; int myvalue = 2 * पीआई; कर?क्या आप कह रहे हैं कि पीआई को घोषित घोषित नहीं किया जाना चाहिए? यदि फ़ंक्शन द्वारा लौटाया गया मूल्य बदलने वाला नहीं है, तो यह स्थिर है, इसलिए इसे घोषित करना उचित है। –

+0

@ जेसन: काफी उचित लेकिन काफी अनावश्यक, यही कारण है कि उपकरण इसे चेतावनी के रूप में मान रहे हैं और कोई त्रुटि नहीं। आपके उदाहरण में 'const' * अनावश्यक नहीं है। –

+2

यह वही बात नहीं है। अगर मेरे पास 'getPi() 'है, जिसमें केवल' वापसी पीआई 'है, तो लौटाया गया मूल्य' const' नहीं है। यह * पास-दर-मूल्य (और वापसी-दर-मूल्य) भाषा सम्मेलनों की वजह से * कॉन्स्ट' नहीं हो सकता है। –

2

हां। मैं "स्पष्ट रूप से" कोड लिखने की सलाह दूंगा, क्योंकि यह आपके द्वारा किए गए कोड को पढ़ने के दौरान किसी को भी (स्वयं सहित) को स्पष्ट करता है। आप अन्य प्रोग्रामर के लिए पढ़ने के लिए कोड लिख रहे हैं, संकलक और स्थैतिक विश्लेषण उपकरण की सनकी को खुश करने के लिए नहीं!

(हालांकि, आपको सावधान रहना होगा कि ऐसा कोई भी "अनावश्यक कोड" उत्पन्न होने वाले विभिन्न कोड उत्पन्न नहीं करता है!)

स्पष्ट कोडिंग में सुधार पठनीयता/रख-रखाव के कुछ उदाहरण:

  • मैं गणित भाव के कुछ भागों के आसपास कोष्ठक जगह स्पष्ट रूप से मैं क्या चाहते निर्दिष्ट करने के लिए। यह यह किसी भी पाठक मैं क्या मतलब को स्पष्ट करता है, और मेरे बारे में चिंता (या साथ ay गलती करते हैं) पूर्वता नियमों के होने की बचत होती है:,

     
    int a = b + c * d/e + f;  // Hard to read- need to know precedence 
    int a = b + ((c * d)/e) + f; // Easy to read- clear explicit calculations 
    

  • C++ यदि आप व्युत्पन्न वर्ग में एक आभासी समारोह को ओवरराइड, तो आप इसे "वर्चुअल" का उल्लेख किए बिना घोषित कर सकते हैं। कोड पढ़ने वाला कोई भी यह नहीं बता सकता कि यह एक वर्चुअल फ़ंक्शन है, जो विनाशकारी रूप से भ्रामक हो सकता है! हालांकि आप वर्चुअल कीवर्ड का सुरक्षित रूप से उपयोग कर सकते हैं:

    virtual int MyFunc()
    और यह आपके क्लास हेडर को पढ़ने वाले किसी को भी स्पष्ट करता है कि यह विधि वर्चुअल है। (इस "सी ++ सिंटैक्स बग" को इस मामले में "ओवरराइड" कीवर्ड के उपयोग की आवश्यकता के कारण सी # में तय किया गया है - अगर किसी को भी "अनावश्यक वर्चुअल" को याद करने की आवश्यकता होती है तो यह एक सबूत है)

ये दोनों स्पष्ट उदाहरण हैं जहां "अनावश्यक" कोड जोड़ना कोड को और अधिक पठनीय और बग से कम प्रवण करेगा।

+2

आप एक ही चीज़ के बारे में बात नहीं कर रहे हैं। जैसा कि @ पीपीजी कहते हैं, ** मूल्य ** 'const' या कुछ और नहीं हो सकता है। केवल वस्तुओं कर सकते हैं। यह कहकर कि किसी चीज पर 'कॉन्स्ट' लेबल चिपकाना मूल्यवान है जो 'कॉन्स्ट' द्वारा परिभाषा नहीं है, यह स्पष्ट रूप से एक बुरा विचार है। यह अनावश्यक रूप से अर्थशास्त्र को भ्रमित करता है। –

संबंधित मुद्दे