2014-12-31 4 views
6

कोड का निम्न भाग एक सूचक से एक पूर्णांक जो एक आदर्श भावनामुझे एक इंटरेक्टर को पॉइंटर कास्टिंग करने के लिए चेतावनी क्यों नहीं मिलती है?

int foo[] = {1, 2, 3}; 
#define bar(x) foo[(int)(x) % 3] 
char *baz = "quux"; 
bar(baz); 

बनाता है दूसरी ओर करने के लिए कास्टिंग के लिए एक चेतावनी देता है, निम्नलिखित कोड तथ्य से किसी चेतावनी के बिना संकलित (चाहे जो भी हो एक रनटाइम त्रुटि) का कारण

#include <ctype.h> 
// some code 
char *baz = "quux"; 
isalpha(baz); 

जब मैं ctype.h खोला isalpha को देखने के लिए, मैंने पाया है कि यह एक मैक्रो अन्य मैक्रो की एक जोड़ी का उपयोग करता है है

# define _ISbit(bit) (1 << (bit)) 

enum 
{ 
    // some identifiers 
    _ISalpha = _ISbit (2), 
    // some identifiers 
}; 

extern const unsigned short int **__ctype_b_loc (void) 
__THROW __attribute__ ((__const__)); 

# define __isctype(c, type) \ 
((*__ctype_b_loc())[(int) (c)] & (unsigned short int) type) 

# define isalpha(c) __isctype((c), _ISalpha) 

जैसा कि आप शायद देख सकते हैं, isalpha मैक्रो का विस्तार करने का नतीजा अभी भी सूचकांक baz को int पर स्पष्ट रूप से दर्शाता है। हालांकि, संकलित होने पर यह कोई चेतावनी नहीं देता है। तो जाहिरा तौर पर कोड के दोनों टुकड़े एक ही कार्रवाई करने (यानी, किसी एक int को char * कास्टिंग), अभी तक एक एक चेतावनी देता है और अन्य नहीं करता है। क्यूं कर?

नोट: कोड के इन टुकड़ों वाले प्रोग्रामों को संकलित करने के लिए एक ही विकल्प के साथ संकलन आदेशों का उपयोग किया गया था।

संकलक संस्करण:

gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2 
+1

पहले टुकड़ा मुझे 'gcc' और' -Wall -std = c99 -pedantic' विकल्पों के साथ किसी भी चेतावनी नहीं देता है। वास्तव में – ouah

+0

। क्या आप कंपाइलर, संस्करण इत्यादि पर जानकारी जोड़ सकते हैं? –

+0

@उह यहाँ एक [स्क्रीनशॉट] (http://i.imgur.com/UghzkIz.png) है! – Kareem

उत्तर

9

पहला प्रोग्राम gcc4.7 के साथ चेतावनी नहीं देता है लेकिन संस्करण 4.8 के साथ चेतावनी देता है।

दूसरा प्रोग्राम चेतावनी नहीं देता है क्योंकि मैक्रो परिभाषा सिस्टम हेडर में है। दूसरे कार्यक्रम के साथ चेतावनी प्राप्त करने के लिए -Wsystem-headers जोड़ें।

जीसीसी प्रलेखन से (जोर देना मेरा)

-Wsystem-headers

Print warning messages for constructs found in system header files. Warnings from system headers are normally suppressed, on the assumption that they usually do not indicate real problems and would only make the compiler output harder to read.

+1

'-विसिस्टम-हेडर' के साथ मैक्रो परिभाषा * में कास्ट * के बारे में चेतावनी दी गई है। मुझे प्राप्त विशिष्ट चेतावनी "पॉइंटर से अलग आकार के पूर्णांक में डाली जाती है"। अगर मैं '-सिस्टम-हेडर-एम 32' के साथ संकलित करता हूं, तो 'int' और 'char *' दोनों 32 बिट्स हैं, चेतावनी दूर हो जाती है। कास्ट अभी भी संदिग्ध है (और, इस मामले में, अर्थहीन), लेकिन संकलक इसके बारे में चेतावनी नहीं देता है क्योंकि इसमें कोई आकार परिवर्तन नहीं होता है। –

+0

@ किथ थॉम्पसन यदि आप पहले प्रोग्राम और 'दूसरे प्रोग्राम' को जोड़ते हैं तो दूसरे प्रोग्राम में अब चेतावनी नहीं होगी। जो मुझे लगता है कि विवादित है चेतावनी का नाम '-पॉइंटर-टू-इंट-कास्ट' उस पर भ्रामक है, केवल तभी चेतावनी देता है जब आप एक पूर्णांक में पॉइंटर डालें और यदि सूचक का आकार और पूर्णांक प्रकार भिन्न होता है। – ouah

4

सी मानक किसी भी मानक पुस्तकालय समारोह परमिट इसके अलावा एक मैक्रो के रूप में लागू किया जाना। जैसे मेक्रो परिभाषा (N1570 खंड 7.1.4) के लिए आवश्यकताएँ हैं:

Any function declared in a header may be additionally implemented as a function-like macro defined in the header, so if a library function is declared explicitly when its header is included, one of the techniques shown below can be used to ensure the declaration is not affected by such a macro. Any macro definition of a function can be suppressed locally by enclosing the name of the function in parentheses, because the name is then not followed by the left parenthesis that indicates expansion of a macro function name. For the same syntactic reason, it is permitted to take the address of a library function even if it is also defined as a macro. The use of #undef to remove any macro definition will also ensure that an actual function is referred to. Any inv ocation of a library function that is implemented as a macro shall expand to code that evaluates each of its arguments exactly once, fully protected by parentheses where necessary, so it is generally safe to use arbitrary expressions as arguments. Likewise, those function-like macros described in the following subclauses may be invoked in an expression anywhere a function with a compatible return type could be called.

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

यदि कोई वास्तविक फ़ंक्शन कॉल है, तो char*int तर्क की अपेक्षा रखने वाले वास्तविक फ़ंक्शन के लिए char* तर्क गुजरना एक बाधा उल्लंघन है, जिसके लिए निदान की आवश्यकता होती है। वहाँ char* से int करने के लिए कोई अंतर्निहित रूपांतरण है।

यहां एक छोटा प्रोग्राम है जो मुद्दे को दर्शाता है:

#include <ctype.h> 
int main(void) { 
    char *p = "hello"; 
    isalpha(p); // line 4, possible macro invocation 
    (isalpha)(p); // line 5, actual function call 
#undef isalpha 
    isalpha(p); // line 7, actual function call 
} 

और यहाँ gcc -std=c11 -pedantic साथ यह संकलन (जीसीसी 4.8.2) का परिणाम है:

c.c: In function ‘main’: 
c.c:5:5: warning: passing argument 1 of ‘isalpha’ makes integer from pointer without a cast [enabled by default] 
    (isalpha)(p); // line 5, actual function call 
    ^
In file included from c.c:1:0: 
/usr/include/ctype.h:111:1: note: expected ‘int’ but argument is of type ‘char *’ 
__exctype (isalpha); 
^ 
c.c:7:5: warning: passing argument 1 of ‘isalpha’ makes integer from pointer without a cast [enabled by default] 
    isalpha(p); // line 7, actual function call 
    ^
In file included from c.c:1:0: 
/usr/include/ctype.h:111:1: note: expected ‘int’ but argument is of type ‘char *’ 
__exctype (isalpha); 
^ 

आन लाइन 5, कोष्ठकों के आसपास isalpha मैक्रो विस्तार को रोकें, फ़ंक्शन को स्वयं प्रकट करें। लाइन 7 पर, वास्तविक कार्य का खुलासा किया गया है क्योंकि मैक्रो परिभाषा को हटा दिया गया है।

एक वास्तविक फ़ंक्शन कॉल निहित रूपांतरण करता है, एक कलाकार नहीं; चूंकि char* से int तक कोई अंतर्निहित रूपांतरण नहीं है, इसलिए संकलक एक निदान जारी करता है।(यह एक घातक चेतावनी जारी कर सकता है, लेकिन जीसीसी निहित रूपांतरणों के बारे में कुछ हद तक ढीला है, हालांकि एक चेतावनी मानक की आवश्यकताओं को पूरा करती है।) मैक्रो के साथ, रूपांतरण एक स्पष्ट कास्ट ऑपरेटर द्वारा किया जाता है, जिसे संकलक द्वारा चेतावनी नहीं दी जाती है चूक।

ध्यान दें कि, कार्यान्वयन के आधार पर, सभी तीन कॉल वास्तविक फ़ंक्शन कॉल हो सकते हैं। मानक पुस्तकालय कार्यों के लिए मैक्रो परिभाषा वैकल्पिक हैं। जीएनयू सी लाइब्रेरी isalpha के लिए एक मैक्रो परिभाषा प्रदान करती है क्योंकि मैक्रो परिभाषा फ़ंक्शन कॉल से काफी अधिक कुशल हो सकती है (हालांकि इनलाइन फ़ंक्शन समान रूप से सक्षम हो सकता है)।

+0

यह ओपी के प्रश्न का उत्तर नहीं देता – pat

+0

@pat: मेरा मानना ​​है कि यह करता है। क्या आप उस पर विस्तार करना चाहते हैं? और मैंने अपनी व्याख्या का विस्तार किया है; अंतिम पैराग्राफ के बगल में देखें। –

+1

ओपी प्राप्त चेतावनी सूचक से पूर्णांक तक एक अंतर्निहित रूपांतरण के बारे में नहीं थी, लेकिन विभिन्न आकार के सूचक से पूर्णांक * के लिए एक स्पष्ट कलाकार के बारे में * (संभवतः, उसके पास एक प्रणाली है जहां पॉइंटर्स 'int' के समान आकार नहीं हैं रों)। उन्हें 'इस्लाफा' मैक्रो में स्पष्ट कलाकारों से एक ही चेतावनी प्राप्त होनी चाहिए क्योंकि उन्होंने अपने स्वयं के कोड में समान कलाकार से किया था, लेकिन उन्होंने नहीं किया। – pat

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

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