2011-05-01 24 views
5

निम्नलिखित सी कार्यक्रम पर विचार करें:क्या यह अपरिभाषित व्यवहार का आह्वान करता है?

#include <stdio.h> 

int main(){ 
    int a =-1; 
    unsigned b=-1; 
    if(a==b) 
     printf("%d %d",a,b); 
    else 
     printf("Unequal"); 
    return 0; 
} 

लाइन printf("%d %d",a,b); में, "%d" एक अहस्ताक्षरित प्रकार मुद्रित करने के लिए प्रयोग किया जाता है। क्या यह अपरिभाषित व्यवहार का आह्वान करता है और क्यों?

उत्तर

5

आप स्पष्ट रूप से va_arg मैक्रो fprintf (7.19.6.1/9) के लिए दस्तावेज में, <stdarg.h> से उपयोग करने के लिए एक पैरामीटर है कि एक int (7.15.1.1/2) के रूप में एक unsigned के रूप में पारित किया गया था को पुनः प्राप्त करने की अनुमति है हालांकि जो printf पर भी लागू होता है, यह स्पष्ट रूप से बताता है कि यदि कोई तर्क प्रारूप विनिर्देशक के लिए सही प्रकार नहीं है - एक अनमोडिफाइड %d के लिए, यह int है - तो व्यवहार परिभाषित नहीं किया गया है।

एक टिप्पणी में @bdonlan नोटों के रूप में, अगर (कुछ N के लिए इस मामले 2^N - 1 में) b का मूल्य तो यह अपरिभाषित व्यवहार होगा का उपयोग कर एक int के रूप में मूल्य का उपयोग करने के प्रयास करने के लिए एक int में प्रदर्शनीय नहीं है किसी भी मामले में va_arg। यह केवल प्लेटफ़ॉर्म पर काम करेगा जहां unsigned का प्रतिनिधित्व कम से कम एक पैडिंग बिट का उपयोग करता है जहां संबंधित int प्रतिनिधित्व का संकेत बिट था।

यहां तक ​​कि इस मामले में जहां (unsigned)-1 का मूल्य एक int में व्यक्त किया जा सकता है, मैं अभी भी इस तकनीकी रूप से अपरिभाषित व्यवहार होने के रूप में पढ़ा है। कार्यान्वयन के हिस्से के रूप में, printf पर पैरामीटर तक पहुंचने के लिए va_args के बजाय जादू में निर्मित उपयोग के कार्यान्वयन के लिए इसे लागू करने की अनुमति दी जाएगी और यदि आप unsigned के रूप में कुछ पास करते हैं, जहां int आवश्यक है तो आपने तकनीकी रूप से अनुबंध का उल्लंघन किया है printf

+0

7.15 में अपवाद .1.1/2 निम्नानुसार पढ़ता है: "यदि प्रकार वास्तविक अगली तर्क के प्रकार के साथ संगत नहीं है [...], व्यवहार अवांछित है, सिवाय इसके कि एक प्रकार एक हस्ताक्षरित पूर्णांक प्रकार है, दूसरा प्रकार है संबंधित हस्ताक्षरित पूर्णांक प्रकार, _ और मान दोनों प्रकारों में प्रतिनिधित्व योग्य है "(जोर मेरा)। चूंकि '-1' दोनों प्रकारों में प्रतिनिधित्व योग्य नहीं है, व्यवहार 7.19.6.1/9 – bdonlan

+0

@bdonlan के बिना भी अपरिभाषित है: तकनीकी रूप से' बी' के पास मान '-1' नहीं है, इसमें मूल्य' 2^N है कुछ 'एन' के लिए -1'। चाहे यह मान 'int' और 'हस्ताक्षरित' दोनों में प्रतिनिधित्व योग्य है प्लेटफार्म निर्भर है - आमतौर पर नहीं, मैं आपको प्रदान करता हूं। –

+0

यदि कोई व्यवहार केवल अपरिभाषित है, तो कुछ कार्यान्वयन-परिभाषित कारक सत्य हैं, तो यह प्रभावी ढंग से अपरिभाषित है, क्योंकि एक अनुरूप कार्यान्वयन INT_MAX और UINT_MAX का मान चुनने के लिए स्वतंत्र है जो इसे प्रिंटफ़ कॉल पर नाक राक्षसों को बुलाएगा। – bdonlan

1

हां, if हमेशा सत्य का मूल्यांकन करेगा और printf को signed के रूप में प्रिंट करने का प्रयास करेगा। चूंकि signed प्रकार में जाल प्रस्तुतिकरण हो सकते हैं, इसलिए यह संकेत हो सकता है कि साइन प्रतिनिधित्व एक पूरक है।

2

मानक इस बिंदु पर 100% स्पष्ट नहीं है। एक ओर, आप va_arg के लिए विनिर्देश, जो कहते हैं (§7.15.1.1/2) मिलती है:

अगर कोई वास्तविक अगले तर्क है, या यदि प्रकार वास्तविक अगले के प्रकार के साथ संगत नहीं है तर्क (के रूप में डिफ़ॉल्ट तर्क प्रोन्नति के लिए अनुसार पदोन्नत), व्यवहार अपरिभाषित है, निम्नलिखित मामलों को छोड़कर:

  • एक प्रकार है एक हस्ताक्षरित पूर्णांक प्रकार, अन्य प्रकार इसी अहस्ताक्षरित पूर्णांक प्रकार है, और मूल्य दोनों प्रकारों में प्रतिनिधित्व योग्य है;
  • एक प्रकार शून्य के लिए सूचक है और दूसरा एक चरित्र प्रकार के लिए एक सूचक है।

दूसरी ओर, आप printf (§7.19.6 के विनिर्देश मिलता है।1/9): किसी भी तर्क संगत रूपांतरण विनिर्देश के लिए सही प्रकार नहीं है

हैं, व्यवहार को देखते हुए अपरिभाषित है "

यह बहुत ज्यादा एक दिया कि printf के साथ बहस को पुनः प्राप्त होगा कि। va_arg, मैं कहूंगा कि आप उन मानों के साथ बहुत सुरक्षित हैं जिन्हें लक्ष्य प्रकार में प्रदर्शित किया जा सकता है, लेकिन अन्यथा नहीं। चूंकि आपने इसे पार करने से पहले एक हस्ताक्षरित रूप से -1 में परिवर्तित कर दिया है, तो मूल्य उस सीमा से बाहर होगा एक हस्ताक्षरित int में प्रतिनिधित्व किया जा सकता है, इसलिए व्यवहार अपरिभाषित होगा।

+0

इसके अलावा (हस्ताक्षरित) -1 बन जाता है (UINT_MAX - 1), जो आमतौर पर INT_MAX की सीमा से परे है ... – bdonlan

+0

@bdonlan: ओह - आप सही हैं। संपादित ... –

+0

मुझे आश्चर्य है कि क्या कोई कार्यान्वयन है जहां '% X' का उपयोग किया जाता है और हस्ताक्षरित मूल्य वाले मित्र अंतर्निहित बिट्स के हेक्साडेसिमल प्रतिनिधित्व को दिखाने के अलावा कुछ भी करते हैं? यदि नहीं, तो यह एक उपयोगी व्यवहार प्रतीत होता है जो मानक में प्रदान किया जाना चाहिए, खासकर जब से बहुत से मौजूदा कोड उस व्यवहार पर निर्भर करते हैं। – supercat

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