जीसीसी में `चे * स्ट्रेन से` अपवर्तित रूपांतरण को निरंतर कैसे प्राप्त करें?


409

इसलिए मैं अत्यधिक बड़े कोडबेस पर काम कर रहा हूं, और हाल ही में gcc 4.3 में अपग्रेड किया गया है, जो अब इस चेतावनी को ट्रिगर करता है:

चेतावनी: स्ट्रिंग निरंतर से 'चार *' में परिवर्तित रूपांतरण

जाहिर है, इसे ठीक करने का सही तरीका हर घोषणा को ढूंढना है

char *s = "constant string";

या फ़ंक्शन कॉल जैसे:

void foo(char *s);
foo("constant string");

और उन्हें const charसंकेत देते हैं। हालांकि, इसका मतलब होगा कि 564 फाइलें, न्यूनतम, जो कि इस समय मैं इस समय प्रदर्शन करना चाहता हूं, एक कार्य नहीं है। अभी समस्या यह है कि मैं साथ चल रहा हूं -werror, इसलिए मुझे इन चेतावनियों को रोकने के लिए किसी तरह की आवश्यकता है। मैं उसे कैसे कर सकता हूँ?


जब आप 554 लाइनों की जगह से निपटने के लिए आते हैं, तो sed एक अच्छा दोस्त है। सुनिश्चित करें कि आप पहले का बैकअप लें।
मैट

2
मैंने इस बात पर चर्चा की कि त्रुटि संदेशों को कैसे दबाया जाए और सही प्रतिस्थापन क्या होनी चाहिए। मेरे पास इसके बारे में कोई राय नहीं है। हालांकि, मुझे लगता है कि मैट सही रास्ते पर है। परिभाषित करें कि आप क्या बदलना चाहते हैं। आपको बस सही नियमित अभिव्यक्ति की आवश्यकता है। कॉपी में बदलाव करें। मूल के साथ उनकी तुलना करने के लिए "भिन्न" का उपयोग करें। Sed का उपयोग करके परिवर्तन करना त्वरित, आसान और मुफ्त है, और अंतर भी त्वरित, आसान और मुफ्त है। इसे आज़माएँ और देखें कि आपको कितने परिवर्तनों की समीक्षा करनी है। पोस्ट करें कि आप क्या बदलना चाहते हैं, और उपयोगकर्ताओं को regex प्रतिस्थापन का सुझाव दें।
थॉमस हेडन

संपूर्ण चर्चा इस बात को याद कर रही है कि यह एक समस्या क्यों है जिसे जीसीसी चेतावनी के अनुसार सभी को ठीक करने की आवश्यकता है। इसका कारण डेविड शवार्ट्ज का उत्तर स्टैकओवरफ्लो . com/questions/56522654/… है ।
andig

जवाबों:


227

मेरा मानना ​​है कि -Wno-write-stringsgcc में पास होना इस चेतावनी को दबा देगा।


6
यह pragmas का उपयोग कर बुनियादी प्रति फ़ाइल पर अक्षम किया जा सकता है।
प्रियांक बोलिया

18
@PriyankBolia bdonlan ने रोब वॉकर के जवाब पर टिप्पणी की कि यह उपयोग कर सकता है #pragma GCC diagnostic ignored "-Wwrite-strings"
21

9
सिवाय इसके कि यदि आप एपीआई को नियंत्रित करते हैं, तो जिस स्थिति में @ जॉन का जवाब, कॉन्स्ट चेयर को स्वीकार करने के लिए हस्ताक्षर बदलने के बारे में * अधिक सही है।
jcwenger

215
यह बुरी तरह से व्यावहारिक है, और मुझे दुख है कि यह उन सभी वोटों को मिला है। चेतावनी वहाँ नहीं है ताकि आप उन्हें अनदेखा करें। चेतावनी आपको बता रही है "यार, आप कुछ ऐसा कर रहे हैं जो गलत हो सकता है, सावधान रहें", और आपको केवल उन्हें दबा देना चाहिए जब आप "शट अप, मैं जानता हूं कि मैं क्या कर रहा हूं" जैसी प्रतिक्रिया चाहता हूं, जो सबसे अधिक संभावना है शिशु प्रोग्रामर के साथ ऐसा नहीं है।
क्वांटम भौतिक विज्ञानी

9
मैं सहमत हूं, आपको चेतावनी से छुटकारा नहीं मिलना चाहिए और इसके बजाय जॉन द्वारा प्रदान किए गए समाधान का उपयोग करना चाहिए। बहुत बुरा यह एक स्वीकृत जवाब है!
जेरोम

563

कोई भी कार्य जिसमें आप स्ट्रिंग शाब्दिक पास "I am a string literal"करते हैं, char const *को इसके बजाय टाइप के रूप में उपयोग करना चाहिए char*

यदि आप कुछ ठीक करने जा रहे हैं, तो इसे ठीक करें।

स्पष्टीकरण:

स्ट्रिंग स्ट्रिंग को प्रारंभ करने के लिए आप स्ट्रिंग शाब्दिक का उपयोग नहीं कर सकते हैं, जिसे संशोधित किया जाएगा, क्योंकि वे प्रकार के होते हैं const char*। कास्टिंग दूर constness बाद में उन्हें संशोधित करने के लिए है अपरिभाषित व्यवहार , ताकि आप अपने नकल करने के लिए है const char*तार charद्वारा charगतिशील रूप से आवंटित में char*ताकि उन्हें संशोधित करने के लिए तार।

उदाहरण:

#include <iostream>

void print(char* ch);

void print(const char* ch) {
    std::cout<<ch;
}

int main() {
    print("Hello");
    return 0;
}

25
हालांकि यह सच है, आपके पास हमेशा 3 पार्टी एपीआई पर नियंत्रण नहीं होता है, जो शायद सही ढंग से उपयोग नहीं कर सकता char */ सकती है const char *, इसलिए उस स्थिति में मैं सामान्य रूप से डाली जाती हूं।
ideasman42

15
@ppumkin दुर्भाग्य से, कई सी मानक पुस्तकालय स्ट्रिंग फ़ंक्शन ऐसे char*तार के लिए भी तर्क लेते हैं जिन्हें संशोधित नहीं किया जाएगा। यदि आप एक पैरामीटर को एक के रूप में लेते हैं char const*और एक मानक फ़ंक्शन को पास करते हैं, char*तो आप इसे हिट करेंगे। यदि लाइब्रेरी फ़ंक्शन स्ट्रिंग में हेरफेर नहीं करेगा, तो आप इसे दूर कर सकते हैं const
जॉन

सिर्फ इसलिए कि यह हमेशा संभव नहीं होता है इसका मतलब यह नहीं है कि यह आम उत्पादन कोड में कई बार चेतावनी के लिए पसंदीदा विकल्प नहीं है।
लवशा

1
मैं अब पूरी तरह से समाधान, और स्ट्रिंग शाब्दिक की कार्यक्षमता को समझता हूं। लेकिन शायद दूसरों को नहीं है, इसलिए मैं एक स्पष्टीकरण की आवश्यकता 'पकड़'
NicoBerrogorry

1
मुझे समझ नहीं आ रहा है कि आपका समाधान कैसे लागू किया जाए :(
desmond13

69

मुझे एक समान समस्या थी, मैंने इसे इस तरह हल किया:

#include <string.h>

extern void foo(char* m);

int main() {
    // warning: deprecated conversion from string constant to ‘char*’
    //foo("Hello");

    // no more warning
    char msg[] = "Hello";
    foo(msg);
}

क्या यह इसे हल करने का एक उचित तरीका है? मेरे पास fooइसे स्वीकार करने के लिए अनुकूलित करने के लिए उपयोग नहीं है const char*, हालांकि यह एक बेहतर समाधान होगा (क्योंकि fooपरिवर्तन नहीं होता है m)।


8
@elcuco, आप क्या प्रस्ताव देंगे? मैं फू को संपादित नहीं कर सका, और एक समाधान खोजने की कोशिश की, जिसमें चेतावनी के दमन की आवश्यकता नहीं थी। मेरे मामले में उत्तरार्द्ध अधिक व्यायाम का विषय था, लेकिन मूल पोस्टर के लिए यह महत्वपूर्ण लग रहा था। जहाँ तक मैं बता सकता हूँ, मेरा उत्तर केवल एक ही है जो मेरी और ओपी की स्थितियों को एक ही समय में हल करेगा, इसलिए यह किसी के लिए एक मूल्यवान उत्तर हो सकता है। अगर आपको लगता है कि मेरा समाधान पर्याप्त नहीं है, तो क्या आप कृपया एक विकल्प प्रदान कर सकते हैं? (जिसमें एडिटिंग फू या चेतावनी को नजरअंदाज करना शामिल नहीं है।)
ब्लैकशिफ्ट

अगर हम मानते हैं कि फू ठीक से कोडित है (जो दुर्भाग्य से कोड 'जोश मैथ्यूज' के बारे में बात नहीं कर रहा है) तो यह सबसे अच्छा समाधान है। ऐसा इसलिए है क्योंकि यदि फ़ंक्शन को वास्तव में स्ट्रिंग 'msg' को बदलने की आवश्यकता होती है, तो इसे एक निरंतर स्ट्रिंग पास करने से कोड टूट जाएगा, है ना? लेकिन वैसे भी यह सवाल का जवाब नहीं देता है क्योंकि त्रुटियां पुराने कोड में पहले से ही हैं, इसलिए नए में नहीं, इसलिए उसे पुराने कोड को वैसे भी बदलना होगा।
जोहो पोर्टेला

यही दृष्टिकोण मैंने भी लिया। और अगर किसी के मामलों के लिए यह खोज कर रहा है की char **में PyArg_ParseTupleAndKeywordsमैं इस तरह कुछ करना:static char kw[][16] = {"mode", "name", "ip", "port"}; static char * kwlist[] = {kw[0], kw[1], kw[2], kw[3], NULL};
dashesy

@elcuco: मुझे यकीन नहीं है कि C ++ स्टैटिक एरेज़ कैसे काम करता है। क्या यह वास्तव में किसी भी डेटा की नकल करेगा, और न केवल सूचक?
अलेक्जेंडर मालाखोव

हालांकि इस दृष्टिकोण में कुछ मामलों में योग्यता हो सकती है जो इसे नेत्रहीन रूप से लागू करना है, IMO के अच्छे से अधिक नुकसान करने की संभावना है। इसे आँख बंद करके लागू करने से लटकने वाले बिंदुओं को आसानी हो सकती है। यह बिंदु रहित स्ट्रिंग प्रतियों के साथ कोड को भी ब्लोट करेगा।
प्लगवॉश

69

Gcc के डायग्नोस्टिक प्राग्मा सपोर्ट, और -W वार्निंग ऑप्शंस (बदली गई: वार्निंग ऑप्शन्स की नई कड़ी ) की सूची देखें।

जीसीसी के लिए, आप यहां#pragma warning बताए गए निर्देशों जैसे निर्देशों का उपयोग कर सकते हैं


54
यह वास्तव में करता है: #pragma GCC डायग्नॉस्टिक "-राइट-स्ट्रिंग्स" को नजरअंदाज कर दिया
20

30

यदि यह एक सक्रिय कोड आधार है, तो आप अभी भी कोड आधार को अपग्रेड करना चाह सकते हैं। बेशक, मैन्युअल रूप से परिवर्तन करना संभव नहीं है, लेकिन मेरा मानना ​​है कि इस समस्या को एक बार और सभी के लिए एक ही sedआदेश द्वारा हल किया जा सकता है । हालांकि, मैंने इसकी कोशिश नहीं की है, इसलिए नमक के एक दाने के साथ निम्नलिखित लें।

find . -exec sed -E -i .backup -n \
    -e 's/char\s*\*\s*(\w+)\s*= "/char const* \1 = "/g' {} \;

यह सभी स्थानों पर नहीं मिल सकता है (यहां तक ​​कि फ़ंक्शन कॉल पर विचार नहीं कर रहा है), लेकिन यह समस्या को कम करेगा और कुछ शेष परिवर्तनों को मैन्युअल रूप से करना संभव करेगा।


7
यह केवल चेतावनी की घोषणा करता है और वैसे भी sed फू के लिए फ़ंक्शन कॉल +1 नहीं करता है: p
João Portela

25

मैं संकलक स्विच का उपयोग नहीं कर सकता। इसलिए मैंने इसे बदल दिया है:

char *setf = tigetstr("setf");

इसके लिए:

char *setf = tigetstr((char *)"setf");

1
+1 - आप अनुप्रयोगों के अंतराल को नहीं बदल सकते हैं, केवल प्रतिद्वंद्विता कर सकते हैं। यह वास्तविक समस्या को ठीक करने के लिए साबित हुआ। अन्य बस संकलक के साथ कुछ मुद्दों के आसपास काम करते हैं।
elcuco

1
जो बात वास्तव में कष्टप्रद है, वह यह है कि बाघों () को (कास्ट चार *) के साथ प्रोटोटाइप किया जाना चाहिए, न कि (चार *)
vy32

2
जब मैं ऐसा करता हूं तो मुझे "चेतावनी: कास्ट चार * * से टाइप करने के लिए" चार * टाइप करें "कॉन्स्टेंस दूर जाती हैं"। मुझे सभी चेतावनियों से छुटकारा पाने के लिए एक const_cast का उपयोग करना पड़ा: const_cast <char *> ("
setf

2
मुझे लगता है कि कास्ट कास्ट इस पृष्ठ पर पहला स्वीकार्य समाधान है (एपीआई परिवर्तन को छोड़कर)।
rwst

25

यहाँ एक फ़ाइल में इनलाइन कैसे किया जाता है, इसलिए आपको अपना Makefile संशोधित करने की आवश्यकता नहीं है।

// gets rid of annoying "deprecated conversion from string constant blah blah" warning
#pragma GCC diagnostic ignored "-Wwrite-strings"

आप बाद में कर सकते हैं ...

#pragma GCC diagnostic pop

25

बदलने के

char *str = "hello";

साथ में

char *str = (char*)"hello";

या यदि आप फ़ंक्शन में कॉल कर रहे हैं:

foo("hello");

इससे बदलें

foo((char*) "hello");

15

के बजाय:

void foo(char *s);
foo("constant string");

यह काम:

void foo(const char s[]);
foo("constant string");

यह ऐसा करने का सही तरीका है क्योंकि आपको किसी फ़ंक्शन के लिए (निरंतर) स्ट्रिंग को पास नहीं करना चाहिए, जो किसी भी तरह एक गैर-स्थिर स्ट्रिंग की अपेक्षा करता है!
jfla

15

C ++ में, const_castनीचे जैसा उपयोग करें

char* str = const_cast<char*>("Test string");

7

Test stringकास्ट स्ट्रिंग है तो आप इस तरह हल कर सकते हैं:

char str[] = "Test string";

या:

const char* str = "Test string";
printf(str);


2

लगातार स्ट्रिंग से चार सूचक तक टाइपकास्टिंग करें

char *s = (char *) "constant string";

1

C ++ में, बदलें:

char *str = "hello";

साथ में:

std::string str ("hello");

और अगर आप इसकी तुलना करना चाहते हैं:

str.compare("HALLO");

1

मुझे समझ नहीं आ रहा है कि आपका समाधान कैसे लागू किया जाए :( - kalmanIsAGameChanger

Arduino स्केच के साथ काम करते हुए, मेरे पास एक समारोह था, जिससे मेरी चेतावनी बन गई।

मूल समारोह: चार StrContains (चार * str, चार * sfind)

चेतावनी को रोकने के लिए मैं जोड़ा स्थिरांक चार के सामने * str और चार * sfind।

संशोधित: चार StrContains (const char * str, const char * sfind)।

सभी चेतावनी देकर चले गए।


यह सही उत्तर है जैसा कि चेतावनी कह रही थी: "चेतावनी: स्ट्रिंग कन्टेनर से 'चार *' में परिवर्तित रूपांतरण।"
नॉर्बर्ट बोरोस

0

इस स्थिति को देखें:

typedef struct tagPyTypeObject
{
    PyObject_HEAD;
    char *name;
    PrintFun print;
    AddFun add;
    HashFun hash;
} PyTypeObject;

PyTypeObject PyDict_Type=
{
    PyObject_HEAD_INIT(&PyType_Type),
    "dict",
    dict_print,
    0,
    0
};

नाम फ़ील्ड देखें, gcc में यह चेतावनी के बिना संकलित है, लेकिन g ++ में यह होगा, मुझे नहीं पता क्यों।


जीसीसी फ़ाइल को सी स्रोत फ़ाइल के रूप में मानता है, जी ++ इसे सी ++ स्रोत फ़ाइल के रूप में मानता है, जब तक -x ओवरराइड नहीं करता है ?? विकल्प। इसलिए अलग-अलग भाषा, c और c ++ में चेतावनी के बारे में सूक्ष्म अंतर हैं।
झाउरुफ़ेई

0

आप कॉल करके स्ट्रिंग स्ट्रिंग से एक लिखने योग्य स्ट्रिंग भी बना सकते हैं strdup()

उदाहरण के लिए, यह कोड एक चेतावनी उत्पन्न करता है:

putenv("DEBUG=1");

हालाँकि, निम्न कोड नहीं है (यह इसे पास करने से पहले हीप पर स्ट्रिंग की एक प्रतिलिपि बनाता है putenv):

putenv(strdup("DEBUG=1"));

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

सुनिए क्या संकलनकर्ता आपको बता रहा है!


6
और यह उस लिखने योग्य स्ट्रिंग के लिए आवंटित मेमोरी को भी लीक करता है।
RBerteig

1
हाँ यह करता है - यह उद्देश्य पर है। उपरोक्त के रूप में एक बार (जैसे, प्रारंभ) कोड के साथ कोई समस्या नहीं है। या, आप स्मृति को स्वयं प्रबंधित कर सकते हैं और इसे जारी कर सकते हैं जब आप इसके साथ कर रहे हैं।
BillAtHRST

1
का विशेष मामला putenv()धोखाधड़ी है - यह उदाहरण का एक अच्छा विकल्प नहीं है (कम से कम, putenv()इस जवाब में क्या करता है की बहुत अधिक चर्चा के बिना नहीं )। यह पूरी तरह से अलग चर्चा है। (ध्यान दें कि POSIX putenv()परिभाषित करने से पहले विरासत कार्यान्वयन के आधार पर, समस्याग्रस्त व्यवहार के लिए POSIX विनिर्देशन समस्याग्रस्त है।) IIRC, GNU C लाइब्रेरी की हाल ही में (सहस्राब्दी) रिलीज़ में एक बग था जो putenv()व्यवहार परिवर्तन से संबंधित था । और वापस बदल दिया जा रहा है।)
जोनाथन लेफ़लर

0

बस g ++ के लिए -w विकल्प का उपयोग करें

उदाहरण:

g ++ -w -o simple.o simple.cpp -lpreadread

याद रखें कि यह अपव्यय से बचने के बजाय टर्मिनल पर चेतावनी संदेश दिखाने से रोकता है।

अब अगर आप वास्तव में इस तरह से कॉन्स्ट्रेक्ट कांस्टेबल उपयोग से बचना चाहते हैं:

const char* s="constant string";  

0

आप -Wno-deprecatedपदावनत चेतावनी संदेशों को अनदेखा करने के विकल्प का उपयोग क्यों नहीं करते ?


0

अभी समस्या यह है कि मैं -वरर के साथ चल रहा हूं

यह आपकी वास्तविक समस्या है, IMO। आप (char *) से (const char *) जाने के कुछ स्वचालित तरीके आज़मा सकते हैं, लेकिन मैं उन पर पैसा नहीं लगाऊंगा। आपको कम से कम कुछ कार्यों के लिए एक मानव को शामिल करना होगा। अल्पावधि के लिए, बस चेतावनी को अनदेखा करें (लेकिन IMO इसे छोड़ दें, या इसे कभी भी ठीक नहीं किया जाएगा) और -Werror को हटा दें।


9
कारण लोगों के लिए उपयोग -Werror कि चेतावनी तो है है तय मिलता है। अन्यथा वे कभी तय नहीं होते।
ज़ेन लिंक्स

2
लोगों द्वारा उपयोग करने का कारण यह है कि वे केवल खिलौना परियोजनाओं पर काम करते हैं, या वे मर्दाना हैं। जब आपका 100k + LOC है तो GCC अपडेट के कारण आपका कोड बनाना एक वास्तविक समस्या है। Dito। किसी ने कबाड़ की चेतावनियों से छुटकारा पाने के लिए "-वॉन-राइट-स्ट्रिंग्स" जैसे कबाड़ को जोड़ दिया (जैसे कि इस पोस्ट में सबसे ज्यादा रेटिंग वाली टिप्पणी से पता चलता है)।
जेम्स एंटिल

2
उस विषय में स्पष्ट असहमति है, उदाहरण के लिए programmer.97things.oreilly.com/wiki/index.php/…
João Portela

3
@ नाम: आप एक दिलचस्प बिंदु बनाते हैं, लेकिन एक बेहतर तरीका है। यह चेतावनी को तुरंत ठीक नहीं करने के लिए व्यर्थ लगता है - जब नए कोड ने पुरानी चेतावनियों को दूर नहीं किया है तो नए कोड का आह्वान करने पर आप कैसे पहचानते हैं? मेरे अनुभव में, यह सिर्फ लोगों को चेतावनी की अनदेखी करने की ओर ले जाता है जिसे उन्हें नजरअंदाज नहीं करना चाहिए।
नोबार

2
@ नाम: हमारी खिलौना परियोजना 1.5 + एम एलओसी (बहु भाषा) है। जैसा कि नोबार ने कहा, -वायरर चेतावनी को नजरअंदाज करने से बचता है जो नहीं होना चाहिए और हां, हर बार संकलक का एक नया संस्करण उठता है, हम सभी को फिर से देखना चाहिए। -जवाब लिखने में स्ट्रैस का इस्तेमाल तब किया जाता है, जब किसी फाइल में फाइल तरीके से अजगर रैपर के लिए बूस्ट का इस्तेमाल किया जाता है, क्योंकि हम बूस्ट को फिर से लिखने नहीं जा रहे हैं (और अब 2017 में, हम बूस्ट का इस्तेमाल करना ज्यादा पसंद नहीं करते हैं लेकिन ++ 11/ / cython)। प्रत्येक चेतावनी को नजरअंदाज किया जाना चाहिए फिर समय-समय पर गुणवत्ता की जांच करके यह देखना चाहिए कि क्या अब उन्हें कोड से बचा जा सकता है या यदि यह अभी तक संभव नहीं है।
एमएसएन

0

आप सब का सहायता के लिए धन्यवाद। यहाँ से उठा और यह समाधान आता है। यह स्वच्छ संकलन करता है। अभी तक कोड का परीक्षण नहीं किया है। कल ... शायद ...

const char * timeServer[] = { "pool.ntp.org" }; // 0 - Worldwide 
#define WHICH_NTP            0 // Which NTP server name to use.
...
sendNTPpacket(const_cast<char*>(timeServer[WHICH_NTP])); // send an NTP packet to a server
...
void sendNTPpacket(char* address) { code }

मुझे पता है, टाइमसेवर सरणी में केवल 1 आइटम है। लेकिन और भी हो सकता है। बाकी को स्मृति को बचाने के लिए अभी टिप्पणी की गई थी।


-1
PyTypeObject PyDict_Type=
{ ...

PyTypeObject PyDict_Type=
{
  PyObject_HEAD_INIT(&PyType_Type),
                     "dict",
                     dict_print,
                     0,
                     0
}; 

नाम फ़ील्ड देखें, gcc में यह चेतावनी के बिना संकलित है, लेकिन g ++ में यह होगा, मुझे नहीं पता क्यों।

में gcc (Compiling C) , -नहीं लिखने-तार डिफ़ॉल्ट रूप से सक्रिय है।

में g++ (Compiling C++) -Wwrite-तार डिफ़ॉल्ट रूप से सक्रिय है

यही कारण है कि एक अलग व्यवहार है। हमारे Boost_pythonलिए इस तरह की चेतावनियाँ उत्पन्न करने वाले मैक्रोज़ का उपयोग करना । इसलिए -Wno-write-stringsजब हम हमेशा उपयोग करते हैं तो हम C ++ का संकलन करते हैं-Werror


-1

एक स्ट्रिंग को constसमस्या के समाधान के रूप में घोषित करें :

char const*s = "constant string";
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.