2012-05-20 13 views
10

ठीक है, मैंने विंडोज 7 पर मिनीजीडब्लू (जीसीसी 4.6.2) के साथ सी फाइल को संकलित करने में एक अजीब समस्या में भाग लिया है। प्रश्न में फ़ाइल में शामिल है निम्नलिखित सी कोड:मिनजीडब्ल्यू जीसीसी: "अज्ञात रूपांतरण प्रकार चरित्र 'एच'" (स्नप्रिंटएफ)

#include <stdio.h> 

int main(int argc, char *argv[]) { 
    printf("%2hhX\n", 250); 
    char c[80]; 
    snprintf(c, sizeof(c), "%2hhX", 250); 
    printf("%s\n", c); 
    return 0; 
} 

संकलन इस तरह पता चला:

$ gcc.exe -std=c99 -pedantic -Wall test.c 
test.c: In function 'main': 
test.c:6:2: warning: unknown conversion type character 'h' in format [-Wformat] 
test.c:6:2: warning: too many arguments for format [-Wformat-extra-args] 

अब, मुझे क्या अजीब बात है कि यह लाइन 6 पर snprintf कॉल के बारे में शिकायत नहीं, बल्कि लाइन पर printf कॉल है 4. क्या मुझे कुछ याद आ रहा है या चेतावनी सिर्फ गलत है? साथ ही, प्रारूप स्ट्रिंग "%2hhX" प्रारूप के लिए शायद बेहतर समकक्ष है? (मैं चार चर चर हेक्साडेसिमल मानों को मुद्रित करने की कोशिश कर रहा हूं।)

+0

दिलचस्प है, यह जीसीसी 4.3.4 के साथ ठीक काम करता है: http://ideone.com/LAPP9। मैंने 4.1.2 के साथ भी कोशिश की है, और यह भी ठीक है। –

+0

मिनजीडब्ल्यू जीसीसी 4.6.1 का उपयोग करके मुझे 'printf() 'और' snprintf() 'दोनों पर चेतावनियां मिलती हैं - आप किस मिनजीडब्ल्यू डिस्ट्रो का उपयोग कर रहे हैं? मैं वर्तमान में टीडीएम वितरण का उपयोग कर रहा हूं। –

+0

@ माइकलबुर: ओह, मुझे यह भी एहसास नहीं हुआ कि कई मिनजीडब्ल्यू डिस्ट्रोज़ थे। मैं "मानक" का उपयोग कर रहा हूं, मुझे लगता है ([mingw.org] (http://www.mingw.org/), https://sourceforge.net/projects/mingw/files/Installer/mingw के साथ स्थापित जाओ-Inst /)। क्या इससे कोई फर्क पड़ता है? – Socob

उत्तर

17

ऐतिहासिक रूप से, मिनजीडब्ल्यू एक अजीब परिस्थिति में रहा है, खासकर जहां तक ​​सी 99 समर्थन जाता है। MinGW ज्यादातर msvcrt.dll रनटाइम पर निर्भर करता है जो विंडोज के साथ वितरित किया जाता है, और वह रनटाइम C99 का समर्थन नहीं करता है।

तो मिनजीडब्ल्यू के पुराने संस्करणों के साथ, आप सी 99-विशिष्ट प्रारूप विनिर्देशकों का उपयोग करते समय सी 99 मोड में समस्याओं में भाग ले सकते हैं। ऐतिहासिक रूप से, जीसीसी ने सीएस विनिर्देशकों के लिए msvcrt.dll की समर्थन की कमी के लिए कोई विशेष आवास नहीं बनाया। तो आप उन परिस्थितियों में आ जाएंगे जहां -Wformat एक प्रारूप के बारे में चेतावनी नहीं देगा जो काम नहीं करेगा। -

हालात दोनों पक्षों पर सुधार कर रहे हैं जीसीसी जैसे कि जब एमएस क्रम के साथ प्रयोग किया -Wformat के लिए विशिष्ट समर्थन, है:

  • तो -Wpedantic-ms-format कि जीसीसी शिकायत नहीं होगा "I32" के बारे में और "I64" (यह भले ही दस्तावेज, मैं अभी भी यह और भी 4.7.0 में गैर मान्यता प्राप्त होने के बारे में एक शिकायत प्राप्त - शायद यह एकदम नया)
  • __attribute__((__format__))

करने के लिए ms_printf विकल्प नहीं है पर दूसरी ओर, एमएनजीडब्ल्यू ने थोड़ी देर के लिए अपना खुद का snprintf() प्रदान किया है, क्योंकि एमएसवीसी के संस्करण, _snprintf(), काफी अलग तरीके से व्यवहार करते हैं। हालांकि, एमजीजीडब्ल्यू ने printf() पर msvcrt.dll में लंबे समय तक निर्भर किया, इसलिए printf() के लिए सी 99 प्रारूप विनिर्देशक काम नहीं कर पाए। कुछ बिंदु पर मिनजीडब्ल्यू ने इसे printf() और दोस्तों के अपने संस्करण प्रदान करना शुरू किया ताकि आप उचित सी 99 (और जीएनयू?) समर्थन प्राप्त कर सकें। हालांकि, ऐसा लगता है कि रूढ़िवादी पक्ष पर होना, इन्हें शुरुआत में msvcrt.dll संस्करणों को प्रतिस्थापित नहीं किया गया था। उनके पास __mingw_printf() जैसे नाम हैं।

यह 4.6.1 और 4.7.0 के बीच किसी बिंदु पर दिखता है, मिनजीडब्ल्यू हेडर ने msvcrt.dll फ़ंक्शन के लिए प्रतिस्थापन के रूप में MinGW आपूर्ति किए गए संस्करणों का उपयोग करना शुरू किया (कम से कम यदि आपने C99 निर्दिष्ट किया है)।

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

आप MinGW समर्थन "hhX" की कितनी अच्छी तरह अपने संस्करण देखने के लिए कोड की निम्न snipet की कोशिश करना चाहते हो सकता है:

printf("%hhX\n", 0x11223344); 
__mingw_printf("%hhX\n", 0x11223344); 

मुझे यकीन है कि समस्या आप में चला रहे हैं ठीक करने के लिए सुझाव देने के लिए क्या नहीं कर रहा हूँ - मुझे लगता है कि आप MinGW stdio.h शीर्षलेख को पैच करने में सक्षम हो सकते हैं ताकि उसके पास printf फ़ंक्शंस पर __attribute__((__format__ (gnu_printf, ...))) विशेषता हो (वे नए stdio.h में नहीं हैं, इसलिए जीसीसी प्रारूप का समर्थन करने के बारे में इसका डिफ़ॉल्ट विचार उपयोग करेगा)।

जब आप कहते हैं कि __attribute__((__format__ (FORMAT, ...))), FORMAT का मूल्य हो सकता है (printf का संबंध है जहाँ तक) निम्न में से एक:

+0

आपका कोड स्निपेट कोई चेतावनी नहीं देता है जब मैं इसे ऊपर से विकल्पों के साथ संकलित करता हूं और '44' प्रिंट करता हूं, जैसा कि कोई अपेक्षा करता है; ऐसा लगता है कि विशेष रूप से केवल 'snprintf' मेरी स्थापना पर चेतावनी से प्रभावित होता है। फिर भी, ऊपर पोस्ट किया गया कोड दो बार 'एफए' प्रिंट करता है, इसलिए यह कार्य सही तरीके से काम कर रहा है। तो, अनिवार्य रूप से, चेतावनी वास्तव में गलत है और यह केवल मिनीजीडब्ल्यू और जीसीसी के साथ एक quirk है? यदि हां, तो मुझे बस इतना ही पता होना चाहिए - मैं सिर्फ यह जानना चाहता था कि क्या मुझे कोड में कुछ याद आया या अगर मैं चेतावनी को अनदेखा कर सकता हूं। – Socob

+0

धन्यवाद। यहां तक ​​कि MinGW 4.9.1 '__mingw_printf' पर भी वह चेतावनी के बिना मेरे लिए काम करता है। इसे सामान्यता के लिए मैक्रो में लपेटेगा। – legends2k

3

अन्य जवाब देने के लिए इसके अलावा, यहां जीसीसी में printf प्रारूप चेक पर कुछ और जानकारी है : printf, gnu_printf, ms_printf

ms_printf जीसीसी मानता है कि फ़ंक्शन माइक्रोसॉफ्ट विजुअल स्टूडियो सीआरटी प्रिंटफ परिवार कार्यों के लिए एक प्रारूप स्ट्रिंग लेता है। इसका मतलब है कि जीसीसी z, hh और ll की शिकायत करेगा, लेकिन चेतावनी के बिना I64 पास करेगा।

gnu_printf जीसीसी ने जीएनयू libc printf कार्यान्वयन के तहत जीएनयू libc printf कार्यान्वयन (या शायद सिर्फ एक POSIX/C99-compliant printf कार्यान्वयन, मुझे यकीन नहीं है) बनाता है। इसलिए जीसीसी I64 और अन्य माइक्रोसॉफ्ट एक्सटेंशन की शिकायत करेगा, लेकिन z, hh और ll स्वीकार करेगा।

printf विंडोज के लिए संकलन करते समय ms_printf के लिए उपनाम है, और अन्यथा gnu_printf के लिए उपनाम है।

ध्यान दें कि यह चेक वास्तविक प्रिंटफ कार्यान्वयन के लिए पूरी तरह से ऑर्थोगोनल है। यह देखना आसान है कि क्या आप अपना खुद का प्रिंटफ-जैसे फ़ंक्शन लिखते हैं और __attribute__((__format__ (FORMAT, ...))) डालते हैं - जीसीसी FORMAT के आधार पर अलग-अलग चीज़ों के बारे में शिकायत करेगी, लेकिन आप जो कुछ भी फ़ंक्शन के अंदर चाहते हैं वह कर सकते हैं।

उपलब्ध printf कार्यान्वयन है कि मैं के बारे में पता:

  • MinGW एएनएसआई stdio (-D__USE_MINGW_ANSI_STDIO=1 साथ संकलन) MinGW.org और MinGW-W64 toolchains में। ms_printf (पूरी तरह से?) और gnu_printf प्रारूप का आंशिक रूप से पालन करता है (आंशिक रूप से - स्थितित्मक तर्कों का समर्थन नहीं करता है)।
  • एमएसवीसीआरटी (-D__USE_MINGW_ANSI_STDIO=1 के बिना संकलित)। ms_printf (डुह ...) का अनुपालन करता है, gnu_printf के साथ अनुपालन बहुत कम है और रनटाइम संस्करण पर निर्भर करता है (पुराने संस्करण ll का समर्थन नहीं करते हैं, नए लोग करते हैं; z और hh अब तक किसी भी संस्करण में समर्थित नहीं हैं; जीसीसी आनंद से अनजान है हालांकि इन घटनाओं, और सबसे खराब मामला मानते हैं, वीसी 6.0 युग से msvcrt, ऐसा लगता है)।
  • gnulib। ms_printf और gnu_printf का पूरी तरह से (या पूरी तरह से निकट) का पालन करता है।

stdio.h MinGW.org में शीर्षलेख attribute format का उपयोग नहीं करता है।

MinGW-W64 में stdio.h हैडर MinGW एएनएसआई stdio कार्यान्वयन के लिए attribute format gnu_printf का उपयोग करता है, लेकिन MSVCRT कार्यान्वयन के लिए कुछ भी उपयोग नहीं करता। फिक्स्ड: MinGW-w64 शीर्षलेख stdio.h के नए संस्करणों में MSVCRT कार्यान्वयन के लिए attribute format ms_printf का उपयोग करेगा।

gnulib printf और gnu_printf के बीच अंतर से पूरी तरह वाकिफ है, और एक या अन्य कुछ जटिल मैक्रो के आधार पर ले जाएगा (शायद, एक उचित कार्यान्वयन का समर्थन करता है कि कौन सा स्वरूप यह होता है का कहना है कि इसके साथ साथ)।

सॉफ्टवेयर के टुकड़े कि (इस समय) में जाना जाता है जीसीसी प्रारूप चेकों के साथ समस्याओं के लिए:

  • फिसलनदार - printf स्वरूप का उपयोग करता है, लेकिन कार्यान्वयन gnulib से है; इसे gnu_printf
  • सीपीथॉन में बदलने के लिए एक उत्कृष्ट बग है - कोड z स्वरूपों से भरा है, लेकिन आधिकारिक बाइनरी एमएसवीसीआरटी के खिलाफ बनाई गई हैं; यह भी इसके विस्तार हेडर में printf स्वरूप का उपयोग करता है, भले ही एक्सटेंशन अक्सर साथ ही z का उपयोग