2010-05-05 13 views
10

इस वेबसाइट पर कई प्रश्न हस्ताक्षर किए गए हैं और हस्ताक्षर किए गए प्रकारों को मिलाते समय और अधिकांश कंपाइलर इस प्रकार की चेतावनियां उत्पन्न करने के बारे में अच्छी नौकरी करते हैं। हालांकि, किसी हस्ताक्षरित प्रकार पर हस्ताक्षरित निरंतर असाइन करते समय जीसीसी की परवाह नहीं होती है!एक हस्ताक्षरित प्रकार के लिए हस्ताक्षरित शाब्दिक असाइन करते समय जीसीसी चेतावनी क्यों नहीं देता है?

/* foo.c */ 
#include <stdio.h> 
int main(void) 
{ 
    unsigned int x=20, y=-30; 
    if (x > y) { 
     printf("%d > %d\n", x, y); 
    } else { 
     printf("%d <= %d\n", x, y); 
    } 
    return 0; 
} 

जीसीसी के साथ संकलन 4.2.1 के रूप में नीचे कंसोल पर कोई उत्पादन का उत्पादन:

$ ./foo 
20 <= -30 

है:

gcc -Werror -Wall -Wextra -pedantic foo.c -o foo 

जिसके परिणामस्वरूप निष्पादन योग्य निम्नलिखित उत्पादन उत्पन्न करता है निम्नलिखित कार्यक्रम पर विचार करें हस्ताक्षर किए गए मान -30 को हस्ताक्षरित पूर्णांक चरपर हस्ताक्षर किए जाने पर GCC कोई चेतावनी या त्रुटि संदेश उत्पन्न नहीं करता है?

+3

ध्यान दें कि आपको 'हस्ताक्षरित int' प्रिंटिंग के लिए% u का उपयोग करना चाहिए। –

+0

@ बास्टियन, वास्तव में; शायद अधिक दिलचस्प बात यह है कि, एंड्रॉइड ने नीचे दिए गए अपने जवाब में बताया, 'printf ("% d")' हस्ताक्षरित मूल्य (42 9 4 9 67266) के बजाय हस्ताक्षरित मूल्य दिखाता है जिसका उपयोग तुलना ऑपरेटर द्वारा किया जाता है! – maerics

+1

यह हस्ताक्षरित int के 2 के पूरक प्रतिनिधित्व के कारण है: http://en.wikipedia.org/wiki/Two%27s_complement (यह प्रतिनिधित्व सी मानक द्वारा गारंटी नहीं है, लेकिन व्यवहार में मैंने कभी एक और प्रतिनिधित्व के बारे में नहीं सुना है अभी भी उपयोग में है) –

उत्तर

14

उपयोग -Wconversion:

~/src> gcc -Wconversion -Werror -Wall -Wextra -pedantic -o signwarn signwarn.c 
cc1: warnings being treated as errors 
signwarn.c: In function 'main': 
signwarn.c:5: error: negative integer implicitly converted to unsigned type 

मुझे लगता है कि यहाँ बात यह है कि जीसीसी वास्तव में चेतावनी पैदा काफी अच्छा है, लेकिन यह (कभी कभी अप्रत्याशित) के मामलों के लिए ऐसा न करने के लिए चूक। उपलब्ध चेतावनियों को ब्राउज़ करना और विकल्पों का एक सेट चुनना एक अच्छा विचार है जो आपको लगता है कि आपकी मदद करेगा। या बस उन सभी, और उस कोड को तब तक पॉलिश करें जब तक वह चमकता न हो! :)

6

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

क्या आपके प्रोग्राम आउटपुट के लिए के रूप में ... एक अहस्ताक्षरित मूल्य उस प्रकार int परिणाम अपरिभाषित व्यवहार है, जो आप वास्तव में क्या अपने प्रयोग में मनाया है में की सीमा से परे है के साथ printf की %d फॉर्मेट स्पेसिफायर का उपयोग करना।

+0

हे, अच्छा पकड़ो। 'printf ("% d ", y);' y = -30; 'की तुलना में पूरी श्रेणी में है। –

+0

ग्रेट प्वाइंट, उदाहरण के लिए, वांछित बिटफील्ड बनाने के लिए मैं नकारात्मक मान का उपयोग कर कल्पना कर सकता हूं। – maerics

+1

हां - ऋणात्मक # के हस्ताक्षर किए जाने के लिए रूपांतरण को 'मॉड्यूलो' को बिना हस्ताक्षर किए गए int के आकार का उत्पादन करने के लिए परिभाषित किया गया है, इसलिए (हस्ताक्षरित) -1 "इसमें सभी 1 के साथ हस्ताक्षरित" कहने का एक बिल्कुल अच्छा तरीका है। जब हस्ताक्षरित संख्या 2 के पूरक के साथ दर्शायी जाती है, तो यह 'रूपांतरण' हस्ताक्षरित के समान ही पैटर्न है। – greggo

1

उपयोग (अप्रमाणित) -1 का उपयोग अक्सर सभी बिट्स सेट करने के लिए किया जाता है और कभी-कभी सी की इस (गलत) सुविधा के कारण के रूप में भी उद्धृत किया जाता है, यहां तक ​​कि उन लोगों द्वारा भी जिन्हें बेहतर पता होना चाहिए। यह न तो स्पष्ट और न ही पोर्टेबल है - अभिव्यक्ति जिसे आप सभी बिट्स सेट करने के लिए उपयोग करना चाहते हैं ~ 0 है।

+0

मैं "uint32_t x = -1;" के अर्थ पर विचार करता हूं, मानक सटीक व्यवहार निर्दिष्ट करता है, और यह 'uint32_t x = ~ 0; 'या' uint32_t x = ~ 0u;' से अधिक पोर्टेबल है साइन-परिमाण प्रणाली, '~ 0' फॉर्म किसी भी 16-बिट सिस्टम पर' x' से 0xFFFF8001ul सेट करेगा, '~ 0u' फॉर्म' x' से 0x0000FFFFul सेट करेगा; '-1' का उपयोग करने वाला फॉर्म चालू होगा कोई भी प्रणाली जो 'uint32_t' को परिभाषित करती है।] – supercat

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