2009-05-13 8 views
12

मुझे सलाह दी गई है कि जीसीसी के साथ निम्नलिखित विकल्पों का उपयोग करें, क्योंकि इससे कई सामान्य त्रुटियों से बचने में मदद मिलती है। यह चेतावनियों का एक गुच्छा चालू करता है और -Werror उन्हें त्रुटियों में बदल देता है।मैं चेतावनियों को कैसे ठीक कर सकता हूं: "हस्ताक्षरित और हस्ताक्षरित के बीच तुलना"?

gcc -pedantic -W -Wall -Wextra -Wshadow -Wstrict-overflow=5 -Wwrite-strings -std=c99 -Werror 

निम्नलिखित परीक्षण कोड को देखते हुए:

#include <stdio.h> 

int main(void) 
{ 
    int arr[8]={0,10,20,30,40,50,60,70}; 
    int x; 

    printf("sizeof(arr): %d\n", sizeof(arr)); 
    printf("sizeof(int): %d\n", sizeof(int)); 

    for(x = 0; x < sizeof(arr)/sizeof(int); x++) 
    { 
     printf("%d\n",arr[x]); 
    } 

    return 0; 
} 

मैं इस:

test.c:11: error: comparison between signed and unsigned 

मुझे पता है कि एक तरह से मैं इसे ठीक कर सकते चेतावनी बंद हो रहा है, लेकिन वे हेवन ' टी ने मुझे इन सेटिंग्स का उपयोग अंत में बंद करने के लिए किया है।

सामान कास्ट करने का एक और तरीका है, लेकिन मुझे बताया गया है कि कास्टिंग को हटा दिया गया है।

इसके अलावा, मैं एक unsigned int में एक्स बना सकता है:

unsigned x; 

लेकिन यह सामान्य समस्या का समाधान नहीं होता जब मैं इन संकलक विकल्पों का उपयोग कर अहस्ताक्षरित मूल्यों के साथ हस्ताक्षर किए मूल्यों की तुलना करने के लिए है। कास्टिंग के बजाए एक क्लीनर तरीका है?

+0

ध्यान दें कि 'sizeof' एक 'size_t' देता है जिसे ['% zu'] (http://stackoverflow.com/q/940087/995714) –

उत्तर

4

यह वास्तव में डेटा प्रकार पर निर्भर करता है। मूल्यों को पूरी तरह से एक प्रकार के लिए कास्टिंग करके इसे टालना संभव है जिसमें हस्ताक्षरित और हस्ताक्षरित प्रकार में उपलब्ध सभी मानों का सुपरसेट शामिल है। उदाहरण के लिए आप एक हस्ताक्षरित 32 बिट और हस्ताक्षरित 32 बिट मान की तुलना करने के लिए 64 बिट हस्ताक्षरित मान का उपयोग कर सकते हैं।

हालांकि यह एक कोने का मामला है और आपको अपने प्रकार के आकार की पुष्टि करने जैसे संचालन करने की आवश्यकता है। आपका सबसे अच्छा समाधान दोनों ऑपरेटरों के लिए एक ही प्रकार का उपयोग करना है।

यदि आपको डालना चाहिए, तो इस बात पर विचार करें कि आप एक अतिप्रवाह पैदा कर सकते हैं और विचार कर सकते हैं कि यह आपके आवेदन के लिए महत्वपूर्ण है या नहीं।

0
test.c:11: error: comparison between signed and unsigned 

आप एक अहस्ताक्षरित पूर्णांक के रूप में एक्स की घोषणा कर सकता है के बाद से size_t अहस्ताक्षरित है

संपादित करें:

कास्ट किए जाने नहीं करना चाहती है, और यह रूप में अहस्ताक्षरित घोषित करने के लिए नहीं करना चाहते हैं, मुझे नहीं लगता कि ऐसा करने के लिए बहुत कुछ है।

शायद बिटवाई ऑपरेशंस इसे हल करने का एक तरीका है, साइन बिट को हटा रहा है। मुझे कहना है, आईएमओ हालांकि यह बहुत संदिग्ध है।

+0

का उपयोग करके मुद्रित किया जाना चाहिए "लेकिन यह सामान्य को हल नहीं करता है समस्या जब मुझे इन कंपाइलर विकल्पों का उपयोग करके हस्ताक्षरित मानों के साथ हस्ताक्षरित मानों की तुलना करना है। क्या कास्टिंग का एक क्लीनर तरीका है? " – George

+1

मैन, क्या आपने प्रश्न का अंत पढ़ा है? – George

+0

हां।लेकिन bitwise ऑपरेशन * कास्टिंग के रूप में माना जा सकता है। – Tom

13

द्वारा

for(size_t x=0;x<sizeof(arr)/sizeof(int);x++) 

बदलें

int x; 
/* ... */ 
for(x=0;x<sizeof(arr)/sizeof(int);x++) 

लेकिन यह सामान्य समस्या का समाधान नहीं होता जब मैं इन संकलक विकल्पों का उपयोग कर अहस्ताक्षरित मूल्यों के साथ हस्ताक्षर किए मूल्यों की तुलना करने के लिए है। क्या कास्टिंग करने का एक क्लीनर तरीका है?

ऐसे मामलों में, यह पता लगाने का प्रयास करें कि हस्ताक्षरित संख्या में कभी कोई मूल्य हो सकता है जो अतिप्रवाह का कारण बनता है। यदि नहीं, तो आप चेतावनी को अनदेखा कर सकते हैं। अन्यथा हस्ताक्षरित प्रकार के लिए एक कास्ट (यदि यह एक ही आकार या हस्ताक्षरित घटक से बड़ा है) पर्याप्त है।

+3

मैं इस उत्तर से सहमत हूं। यह भी ध्यान रखें कि कास्टिंग को बहिष्कृत नहीं किया गया है, लेकिन शायद यह शुरुआत के लिए निराश हो गया है क्योंकि यह आपको कुछ बुरी आदतों में ले जा सकता है। – Borbus

+0

यह सबसे अच्छा जवाब है, लेकिन मैं सी के बारे में एक प्रश्न में सी ++ अवधारणा पेश कर रहा हूं। मैंने थोड़ी देर में सख्त सी का उपयोग नहीं किया है, लेकिन मुझे नहीं लगता कि आप अपने इंडेक्स वैरिएबल को लूप के अंदर घोषित कर सकते हैं जैसे आप कर सकते हैं सी ++। –

+1

@ एड्रियन मैककार्थी: सी 99 देखें, 6.8.5.3.1: [...] "अगर क्लॉज -1 घोषणा है, तो घोषित किसी भी पहचानकर्ता का दायरा घोषणा का शेष है और पूरे लूप, अन्य दो अभिव्यक्ति; यह नियंत्रण अभिव्यक्ति के पहले मूल्यांकन से पहले निष्पादन के क्रम में पहुंच गया है। " – dirkgently

2

बात की जड़ है कि हस्ताक्षर किए और अहस्ताक्षरित मानों की तुलना कुछ अजीब मामलों मानते है। उदाहरण के लिए, हस्ताक्षरित सरणी लंबाई में क्या होता है, उस अधिकतम से अधिक होता है जिसे हस्ताक्षरित int द्वारा दर्शाया जा सकता है। हस्ताक्षरित काउंटर ओवरफ़्लो (सरणी आकार "से कम"), और आप स्मृति को संबोधित करना शुरू करते हैं जिसका मतलब यह नहीं था ...

संकलक यह सुनिश्चित करने के लिए एक चेतावनी उत्पन्न करता है कि आप उनके बारे में सोच रहे हैं। -Werror का उपयोग करके उस त्रुटि को चेतावनी दी जाती है और संकलन को रोकता है।

या तो अपने प्रकार की हस्ताक्षर चुनने के बारे में कठोर हो, या जब आप सुनिश्चित हों कि यह लागू नहीं होता है, तो परेशानी काट दें, या -Werror से छुटकारा पाएं और इसे सभी चेतावनियों को ठीक करने के लिए नीति बनाएं या एक स्पष्टीकरण ...

0

हम को दबाने हमारे दृश्य स्टूडियो में इस चेतावनी को संकलित करता है, क्योंकि यह एक बहुत होता है और लगभग कभी नहीं कुछ भी महत्वपूर्ण होता है। बेशक, सभी कोडिंग मानकों को अनुमति नहीं है।

आप प्रकार सहमत कर सकते हैं (पूर्णांक के बजाय size_t या अहस्ताक्षरित int, उदाहरण के लिए होने के लिए चर घोषित करने), या आप कास्ट कर सकते हैं, या आप अपने संकलन लाइन बदल सकते हैं। यह इसके बारे में।

0

कास्टिंग प्रतिवाद दुविधा के बावजूद, मैं अभी भी पाश के लिए से तर्क को अलग सुझाव देना चाहेंगे।

int range = (int)(sizeof(arr)/sizeof(int)); 
int x; 

for(x = 0; x < range; x++) 
{ 
    printf("%d\n", arr[x]); 
} 

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

1

एक ही विकल्प "-Wno-साइन-की तुलना" :)

+0

इस चेतावनी को छिपाने से वैध बग छिपा सकते हैं। –

+0

इसलिए स्माइली! – frankster

1

एक वैकल्पिक हल चुनिंदा इस विशेष मामले में है कि एक चेतावनी निष्क्रिय करने के लिए किया जाएगा अतिरिक्त झंडा होगा। जीसीसी has pragma diagnostic ignored "-Wsomething" जीसीसी के

// Disable a warning for a block of code: 
#pragma GCC diagnostic push 
#pragma GCC diagnostic ignored "-Wmissing-prototypes" 
// ... Some code where the specified warning should be suppressed ... 
#pragma GCC diagnostic pop 

हाल संस्करणों (मैं वास्तव में कब से यकीन है कि नहीं हूँ, लेकिन 4.8.x यह समर्थन करना चाहिए) इसी -Wsomething विकल्प दिखा। यह महत्वपूर्ण है क्योंकि अधिकांश चेतावनी विकल्प स्पष्ट रूप से सेट नहीं होते हैं, लेकिन विकल्पों के साथ एन ब्लॉक। एक त्रुटि संदेश इस प्रकार दिखाई देगा:

readers.c: In function ‘buffered_fullread’: 
readers.c:864:11: error: comparison between signed and unsigned integer expressions [-Werror=sign-compare] 
    if(got < sizeof(readbuf)) /* That naturally catches got == 0, too. */ 

[-Werror = पंजीकरण तुलना] हिस्सा आपको बताता है कि चेतावनी को दबाने के लिए "Wsomething" के लिए "Wsign-तुलना" का उपयोग कर सकते हैं।

और निश्चित रूप से, आपको केवल वही करना चाहिए जहां यह उचित है (यह पठनीयता में काफी मदद नहीं करता है), उदा। जब संकलक वास्तव में व्यवहार के बारे में चेतावनी देता है (या, यदि आप कोड आधार में बड़े बदलाव नहीं कर सकते हैं)।

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