C ++ ने स्ट्रिंग से स्थिर रूपांतरण को 'char *' में बदल दिया


154

मेरे पास एक वर्ग है a private char str[256];

और इसके लिए मेरे पास एक स्पष्ट निर्माता है:

explicit myClass(const char *func)
{
    strcpy(str,func);
}

मैं इसे कॉल करता हूं:

myClass obj("example");

जब मैं इसे संकलित करता हूं तो मुझे निम्नलिखित चेतावनी मिलती है:

निरंतर परिवर्तन स्ट्रिंग से निरंतर 'चार *' के लिए

ये क्यों हो रहा है?


1
आपको सुरक्षित प्रति के strncpy(str, func, 255)बजाय उपयोग करना चाहिए strcpy(str, func)। और फिर स्ट्रिंग के अंत में '\ 0' जोड़ना न भूलें क्योंकि strncpy इसे जोड़ता नहीं है।
पैट्रिस बर्नसोला

2
अभी भी कहने के लिए "strncpy (str, func, sizeof (str)); str [sizeof (str) - 1] = '\ 0';"
वॉरेन यंग

3
मुझे नहीं लगता कि ऊपर दी गई चेतावनी आपको उद्धृत करती है, हालांकि मुझे यकीन है कि काफी समान कोड होगा। सार्थक उत्तर पाने के लिए, आपको एक न्यूनतम, संकलन उदाहरण पोस्ट करना चाहिए जो चेतावनी पैदा करता है।
sbi

3
@ पैट्रिस, वॉरेन: स्ट्रैन्की का उपयोग न करें, यह स्ट्रैची का सुरक्षित संस्करण नहीं है। उपयोग करें (या फिर से लागू करें) strcpy_s।
स्टीव जेसप

मुझे समस्या है, इसका केवल -X86 बिल्ड के लिए इन मुद्दों को दिखाना और सामान्य सोलारिस या एआरएम (लक्ष्य) के निर्माण के लिए नहीं, इसलिए मैं इसे अनदेखा कर रहा हूं। अभी भी ठीक नहीं मिल सका क्योंकि यह मेरे नमूना कोड के लिए सामान्य रूप से चेतावनी नहीं दिखाता है। आप सभी को धन्यवाद!
mkamthan

जवाबों:


144

यह एक त्रुटि संदेश है जिसे आप देखते हैं जब भी आपको निम्न जैसी स्थिति होती है:

char* pointer_to_nonconst = "string literal";

क्यों? खैर, सी और सी ++ स्ट्रिंग शाब्दिक के प्रकार में भिन्न हैं। C में प्रकार चार का सरणी है और C ++ में यह निरंतर चार वर्ण है। किसी भी मामले में, आपको स्ट्रिंग शाब्दिक के पात्रों को बदलने की अनुमति नहीं है, इसलिए सी ++ में कास्ट वास्तव में प्रतिबंध नहीं है, लेकिन एक प्रकार की सुरक्षा चीज़ से अधिक है। से एक रूपांतरण const char*करने के लिए char*आम तौर पर सुरक्षा की दृष्टि से एक स्पष्ट कलाकारों के बिना संभव नहीं है। लेकिन सी भाषा के साथ पीछे की संगतता के लिए C ++ अभी भी एक को एक स्ट्रिंग शाब्दिक असाइन करने की अनुमति char*देता है और आपको इस रूपांतरण के बारे में एक चेतावनी देता है।

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


17
इस प्रश्न पर मत और मतों को देखते हुए यह दुर्भाग्यपूर्ण है कि ओपी ने कभी भी ऐसा कोड प्रदान नहीं किया जो वास्तव में समस्या को प्रदर्शित करता हो।
शफीक यघमौर

1
आप निर्माणकर्ता constसे हटाकर ओपी के कोड के साथ समस्या को पुन: उत्पन्न कर सकते हैं MyClass... फिर आप इसे constवापस जोड़कर ठीक कर सकते हैं ।
थियोडोर मुर्डॉक

145

चेतावनी:

निरंतर परिवर्तन स्ट्रिंग से निरंतर 'चार *' के लिए

दिया गया है क्योंकि आप कहीं कर रहे हैं (आपके द्वारा पोस्ट किए गए कोड में नहीं) कुछ इस तरह है:

void foo(char* str);
foo("hello");

समस्या यह है कि आप एक स्ट्रिंग शाब्दिक (प्रकार के साथ const char[]) में बदलने की कोशिश कर रहे हैं char*

आप एक const char[]को रूपांतरित कर सकते हैं const char*क्योंकि व्यू पॉइंटर के लिए सरणी का क्षय होता है, लेकिन आप जो कर रहे हैं वह एक परिवर्तनशील को स्थिर बना रहा है।

यह रूपांतरण संभवतः C संगतता के लिए अनुमत है और बस आपको उल्लिखित चेतावनी देता है।


96

जैसा कि उत्तर नं। 2 द्वारा fnieto - फर्नांडो नीटो स्पष्ट रूप से और सही ढंग से वर्णन करता है कि यह चेतावनी दी गई है क्योंकि कहीं न कहीं आपके कोड में आप कर रहे हैं (आपके द्वारा पोस्ट किए गए कोड में नहीं) कुछ इस तरह:

void foo(char* str);
foo("hello");

हालाँकि, यदि आप अपने कोड को चेतावनी मुक्त रखना चाहते हैं, तो बस अपने कोड में संबंधित परिवर्तन करें:

void foo(char* str);
foo((char *)"hello");

यह है, बस stringकरने के लिए निरंतर डाली (char *)


17
वैकल्पिक रूप से, फंक्शन बनाएं: शून्य फू (कॉन्स्ट चार * स्ट्र)
कैपेरोजा

3
@ कैप्रोज़ा ने परम को 'पॉइंटर टू ए कॉन्स्टेंट' घोषित करते हुए इस मामले में भी काम किया। लेकिन इस परिवर्तन के साथ उपयोगकर्ता 'str' पॉइंटर का उपयोग करके पते पर संग्रहीत मान को और अधिक परिवर्तन / पुन: असाइन नहीं कर सकता है जो उपयोगकर्ता कार्यान्वयन भाग में कर सकता है। ताकि आप के लिए बाहर देखने के लिए चाहते हो सकता है कुछ है।
sactiw

1
@sactiw क्या कोई कारण है void foo(char* str)जैसा कि रखना है? मैंने सोचा था कि हम modity नहीं कर सकते strमें fooवैसे भी, यहां तक कि पैरामीटर गैर स्थिरांक के रूप में लिखा है।
kgf3JfUtW

37

3 समाधान हैं:

समाधान 1:

const char *x = "foo bar";

समाधान 2:

char *x = (char *)"foo bar";

समाधान 3:

char* x = (char*) malloc(strlen("foo bar")+1); // +1 for the terminator
strcpy(x,"foo bar");

एरर्स का उपयोग पॉइंटर्स के बजाय किया जा सकता है क्योंकि एक सरणी पहले से ही एक स्थिर पॉइंटर है।


7
समाधान 3 के लिए, वहाँ है strdup। आपके कोड के विपरीत, यह NUL वर्ण को समाप्त करने के लिए स्थान आवंटित करेगा, और आवंटन से अधिक नहीं।
बेन वोइग्ट

2
समाधान 2 से बचा जाना है।
ऑर्बिट

वास्तव में समाधान 2 हो सकता है: C ++ में char * x = static_cast <char *> ("foo bar")।
केहे CAI

3
क्या आप कभी अपने जवाब में टिप्पणियों को एकीकृत करेंगे? समाधान 3 अभी भी खतरनाक रूप से गलत है।
ऑर्बिट में

@LightnessRacesinOrbit क्या आप कृपया उत्तर दे सकते हैं? मुझे समझ नहीं आ रहा है कि आप क्यों कहते हैं कि समाधान 2 और 3 को टाला जाना चाहिए और खतरनाक तरीके से गलत हैं।
ग्लैडलफ

4

वास्तव में एक स्ट्रिंग निरंतर शाब्दिक न तो एक कास्ट चार है * और न ही एक चार * लेकिन एक चार []। यह काफी अजीब है, लेकिन सी ++ विनिर्देशों में नीचे लिखा गया है; यदि आप इसे संशोधित करते हैं तो व्यवहार अपरिभाषित है क्योंकि कंपाइलर इसे कोड सेगमेंट में संग्रहीत कर सकता है।


5
मैं कहूंगा कि यह कास्ट चार है [] क्योंकि एक प्रतिद्वंद्विता के रूप में आप इसे संशोधित नहीं कर सकते।
fnieto - फर्नांडो नीटो

3

शायद आप यह कोशिश कर सकते हैं:

void foo(const char* str) 
{
    // Do something
}

foo("Hello")

इससे मेरा काम बनता है


2

मैं कहीं कोड की शुरुआत में इस मैक्रो को जोड़कर इस समस्या को हल करता हूं। या इसे <iostream>हे में जोड़ें ।

 #define C_TEXT( text ) ((char*)std::string( text ).c_str())

8
"या इसे <iostream> में जोड़ें" क्या ?!
ऑर्बिट में

वहाँ ", हेहे" जो भी कारण से संपादित किया गया था (निहित है कि यह एक मजाक था)
Someguyonympie

C_TEXTफ़ंक्शन कॉल ( foo(C_TEXT("foo"));) के लिए ठीक है , लेकिन अपरिभाषित व्यवहार के लिए रो रहा है यदि मान किसी चर में संग्रहीत किया जाता है char *x = C_TEXT("foo");- जैसे x(असाइनमेंट के अलावा) का कोई भी उपयोग अपरिभाषित व्यवहार है क्योंकि यह जिस मेमोरी को इंगित करता है उसे मुक्त कर दिया गया है।
मार्टिन बोनर

1

इस समस्या का एक कारण (जो कि इस मुद्दे से पता लगाने के लिए और भी कठिन है char* str = "some string"- जिसे अन्य लोगों ने समझाया है) जब आप उपयोग कर रहे हैं constexpr

constexpr char* str = "some string";

ऐसा लगता है कि यह समान व्यवहार करेगा const char* str, और इसलिए यह चेतावनी का कारण नहीं होगा, जैसा कि पहले होता है char*, लेकिन इसके बजाय यह व्यवहार करता है char* const str

विवरण

लगातार सूचक, और एक स्थिर करने के लिए सूचक। के बीच का अंतर const char* str, और char* const strइस प्रकार समझाया जा सकता है।

  1. const char* str: एक कास्ट चार करने के लिए एक सूचक होने की घोषणा की। इसका मतलब यह है कि जिस डेटा को यह पॉइंटर बताता है वह निरंतर है। सूचक को संशोधित किया जा सकता है, लेकिन डेटा को संशोधित करने का कोई भी प्रयास एक संकलन त्रुटि को फेंक देगा।
    1. str++ ;: वैध । हम सूचक को संशोधित कर रहे हैं, न कि डेटा को इंगित किया जा रहा है।
    2. *str = 'a';: निवेश । हम इंगित किए जा रहे डेटा को संशोधित करने का प्रयास कर रहे हैं।
  2. char* const str: तारकोल को एक पॉइंटर पॉइंटर होने की घोषणा करें। इसका मतलब है कि बिंदु अब स्थिर है, लेकिन बताया जा रहा डेटा भी नहीं है। पॉइंटर को संशोधित नहीं किया जा सकता है लेकिन हम पॉइंटर का उपयोग करके डेटा को संशोधित कर सकते हैं।
    1. str++ ;: निवेश । हम सूचक चर को संशोधित करने की कोशिश कर रहे हैं, जो एक स्थिर है।
    2. *str = 'a';: वैध । हम इंगित किए जा रहे डेटा को संशोधित करने का प्रयास कर रहे हैं। हमारे मामले में यह एक संकलन त्रुटि का कारण नहीं होगा, लेकिन एक रनटाइम त्रुटि का कारण होगा , क्योंकि स्ट्रिंग शायद सबसे अधिक संकलित बाइनरी के केवल एक अनुभाग में जाएगी। यह कथन समझ में आता है अगर हमें गतिशील रूप से स्मृति आवंटित की गई थी, जैसे। char* const str = new char[5];
  3. const char* const str: एक कास्ट चार करने के लिए एक कास्ट पॉइंटर होने की घोषणा करें। इस मामले में हम न तो पॉइंटर को संशोधित कर सकते हैं, न ही डेटा को इंगित किया जा सकता है।
    1. str++ ;: निवेश । हम सूचक चर को संशोधित करने की कोशिश कर रहे हैं, जो एक स्थिर है।
    2. *str = 'a';: निवेश । हम इस सूचक द्वारा इंगित किए गए डेटा को संशोधित करने की कोशिश कर रहे हैं, जो निरंतर भी है।

मेरे मामले में मुद्दा यह था कि मैं उम्मीद कर रहा था कि मैं ऐसा constexpr char* strव्यवहार करूंगा const char* str, और नहीं char* const str, क्योंकि दृष्टिगत रूप से यह पूर्व के करीब लगता है।

इसके अलावा, के लिए उत्पन्न चेतावनी constexpr char* str = "some string"से थोड़ा अलग है char* str = "some string"

  1. इसके लिए संकलक चेतावनी constexpr char* str = "some string":ISO C++11 does not allow conversion from string literal to 'char *const'
  2. के लिए संकलक चेतावनी char* str = "some string": ISO C++11 does not allow conversion from string literal to 'char *'

टिप

आप आसानी से समझने योग्य अंग्रेजी कथनों और इसके विपरीत घोषणाओं को परिवर्तित करने के लिए C gibberish converter अंग्रेजी कनवर्टर का उपयोग कर सकते हैं C। यह एक Cएकमात्र उपकरण है, और इस प्रकार समर्थन चीजों (जैसे कि कॉन्स्ट्रेप) को अभ्यस्त नहीं है C++


0

मुझे भी यही समस्या हुई। और मैंने जो कुछ किया वह सिर्फ चार * के बजाय कास्ट चार * जोड़ रहा है। और समस्या हल हो गई। जैसा कि दूसरों ने ऊपर उल्लेख किया है यह एक संगत त्रुटि है। C तार को सरणियों के रूप में मानता है जबकि C ++ उन्हें तारांकित सारणी के रूप में मानता है।


0

इसके लायक क्या है, मुझे लगता है कि यह सरल आवरण वर्ग C ++ स्ट्रिंग्स को परिवर्तित करने के लिए सहायक होगा char *:

class StringWrapper {
    std::vector<char> vec;
public:
    StringWrapper(const std::string &str) : vec(str.begin(), str.end()) {
    }

    char *getChars() {
        return &vec[0];
    }
};

-1

निम्नलिखित समाधान दिखाता है, अपनी स्ट्रिंग को चर पॉइंटर के एक निरंतर सरणी चार पर असाइन करें (स्ट्रिंग स्ट्रिंग की निरंतर सरणी के लिए एक स्थिर सूचक है - प्लस लंबाई जानकारी):

#include <iostream>

void Swap(const char * & left, const char * & right) {
    const char *const temp = left;
    left = right;
    right = temp;
}

int main() {
    const char * x = "Hello"; // These works because you are making a variable
    const char * y = "World"; // pointer to a constant string
    std::cout << "x = " << x << ", y = " << y << '\n';
    Swap(x, y);
    std::cout << "x = " << x << ", y = " << y << '\n';
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.