সি ++ স্ট্রিং ধ্রুবক থেকে 'চর *' এ রূপান্তর বাতিল করা হয়েছে


154

আমার সাথে ক্লাস আছে private char str[256];

এবং এর জন্য আমার স্পষ্ট নির্মাতা রয়েছে:

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

আমি এটি হিসাবে কল:

myClass obj("example");

আমি এটি সংকলন করার সময় আমি নিম্নলিখিত সতর্কতা পাই:

স্ট্রিং ধ্রুবক থেকে 'চর *' এ রূপান্তর বাতিল করা হয়েছে

এটি কেন ঘটছে?


1
নিরাপদ অনুলিপির strncpy(str, func, 255)পরিবর্তে আপনার ব্যবহার করা উচিত strcpy(str, func)। এবং তারপরে স্ট্রিংয়ের শেষে '\ 0' যুক্ত করতে ভুলবেন না কারণ স্ট্রান্সকিপি এটি যুক্ত করে না।
প্যাট্রিস বার্নাসসোলা

2
"স্ট্রেনকিপি (আরআর, ফানক, সাইজ অফ (স্ট্র)) বলতে এখনও নিরাপদ; টিআরএফ [মাপের (টিআর) - 1] = '\ 0';"
ওয়ারেন ইয়াং

3
আমি মনে করি না উপরোক্ত আপনার দ্বারা উদ্ধৃত সতর্কতাটি দিয়েছে, যদিও আমি নিশ্চিত যে বেশিরভাগ অনুরূপ কোডটি হবে। অর্থবহ উত্তর পেতে, আপনার একটি ন্যূনতম, সংকলন উদাহরণ পোস্ট করা উচিত যা সতর্কতা তৈরি করে।
এসবিআই

3
@ পেট্রিস, ওয়ারেন: স্ট্রেনকিপি ব্যবহার করবেন না, এটি স্ট্রাইকপি-র নিরাপদ সংস্করণ নয়। (বা পুনরায় প্রয়োগ) strcpy_s ব্যবহার করুন।
স্টিভ জেসপ

আমি সমস্যাটি পেয়েছি, এটি কেবলমাত্র -186 বিল্ডের জন্য এই সমস্যাগুলি দেখায় এবং সাধারণ সোলারিস বা এআরএম (লক্ষ্য) তৈরির জন্য নয় তাই আমি এটিকে উপেক্ষা করছি। এটি আমার নমুনা কোডের জন্যও সাধারণত কোনও সতর্কতা দেখায় না বলে এখনও একটি স্থিরতা খুঁজে পাওয়া যায়নি। সবাইকে ধন্যবাদ!
এমকামথন

উত্তর:


144

এটি যখনই আপনার নীচের মতো পরিস্থিতি হয় তখন এটি আপনি একটি ত্রুটি বার্তা দেখেন:

char* pointer_to_nonconst = "string literal";

কেন? আচ্ছা, সি এবং সি ++ স্ট্রিংয়ের আক্ষরিক প্রকারের মধ্যে পৃথক। সি তে প্রকারটি চরের অ্যারে এবং সি ++ তে এটি চরের ধ্রুবক অ্যারে। যাই হোক না কেন, আপনাকে আক্ষরিক স্ট্রিংয়ের চরিত্রগুলি পরিবর্তন করতে দেওয়া হয় না, সুতরাং সি ++ এ থাকা কনস্টেরটি আসলেই কোনও বাধা নয় তবে আরও একটি ধরণের সুরক্ষা জিনিস। থেকে একটি রূপান্তর const char*করতেchar* সাধারণত নিরাপত্তার কারণে একটি সুনির্দিষ্ট ঢালাই ছাড়া সম্ভব নয়। তবে সি এর সাথে পিছনে সামঞ্জস্যের জন্য ভাষা সি ++ এখনও একটিতে একটি স্ট্রিংকে আক্ষরিক বরাদ্দ করতে char*দেয় এবং আপনাকে এই রূপান্তরটি হ্রাস করা সম্পর্কে একটি সতর্কতা দেয়।

সুতরাং, কোথাও কোথাও আপনি constআপনার প্রোগ্রামে এক বা একাধিক গুলি নিখুঁতভাবে শুদ্ধ করছেন are তবে আপনি যে কোডটি আমাদের দেখিয়েছেন তা সমস্যা নয় কারণ এটি এই ধরণের অবমূল্য রূপান্তরটি করে না। সতর্কতা অবশ্যই অন্য কোনও জায়গা থেকে এসেছে।


17
এই প্রশ্নের দৃষ্টিভঙ্গি এবং ভোট বিবেচনা করা দুর্ভাগ্যজনক যে ওপি কখনই এমন কোড সরবরাহ করে না যা আসলে সমস্যাটি দেখায়।
শফিক ইয়াঘমোর

1
আপনি নির্মাণকারীর constকাছ থেকে মুছে ফেলার মাধ্যমে ওপির কোড দিয়ে সমস্যাটি পুনরুত্পাদন MyClassকরতে পারেন ... তারপরে আপনি constপিছনে যুক্ত করে এটি ঠিক করতে পারেন can
থিওডোর মুরডক

145

সতর্কবার্তা:

স্ট্রিং ধ্রুবক থেকে 'চর *' এ রূপান্তর বাতিল করা হয়েছে

দেওয়া হয়েছে কারণ আপনি কোথাও করছেন (আপনার পোস্ট করা কোডটিতে নয়) এর মতো কিছু:

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

সমস্যাটি হ'ল আপনি স্ট্রিংকে আক্ষরিক (প্রকারের সাথে const char[]) রূপান্তর করতে চেষ্টা করছেন char*

আপনি একটি রূপান্তর করতে পারেন const char[]করার const char*কারণ অ্যারের পয়েন্টার decays, কিন্তু কি করছ একটি চপল একটি ধ্রুবক করছে।

এই রূপান্তরটি সম্ভবত সি সামঞ্জস্যের জন্য অনুমোদিত এবং কেবল আপনাকে উল্লিখিত সতর্কতা দেয়।


96

উত্তর হিসাবে না। ২ বাই ফিনিয়েটো - ফার্নান্দো নিতো স্পষ্টভাবে এবং সঠিকভাবে বর্ণনা করে যে এই সতর্কতাটি দেওয়া হয়েছে কারণ আপনার কোডের কোথাও আপনি করছেন (আপনার পোস্ট করা কোডটিতে নয়) এর মতো কিছু:

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

তবে, আপনি যদি নিজের কোডটি সতর্কতা-মুক্ত রাখতে চান তবে কেবল আপনার কোডে সম্পর্কিত পরিবর্তন করুন:

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

এটি হল, কেবল stringধ্রুবককে নিক্ষেপ করুন (char *)


17
বিকল্পভাবে, ফাংশনটি তৈরি করুন: অকার্যকর foo (
কনস্টিক

3
@ ক্যাপ্রোজা হ্যাঁ পরমকে 'ধ্রুবকের দিকে নির্দেশক' হিসাবে ঘোষণা করাও এই ক্ষেত্রে কাজ করবে। তবে এই পরিবর্তনের সাথে ব্যবহারকারীর 'আরআর' পয়েন্টার ব্যবহার করে ঠিকানায় সঞ্চিত মানটিকে আর পরিবর্তন / পুনরায় সাইন করতে পারবেন না যা ব্যবহারকারী বাস্তবায়নের অংশে করছেন। সুতরাং এটি এমন কিছু যা আপনার সন্ধান করতে পারে।
স্যুইচ করুন

1
@ স্যাকটিউ void foo(char* str)যেমন রয়েছে তেমন কোনও কারণ আছে ? আমি ভেবেছিলাম আমরা modity পারবনা strমধ্যে fooযাহাই হউক না কেন, এমনকি প্যারামিটার অ const হিসেবে লেখা হয়।
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 হতে পারে: সি ++ এ চর * x = স্ট্যাটিক_কাস্ট <চর *> ("ফু ফু")।
কেহে CAI

3
অনিল আপনি কি নিজের উত্তরগুলিতে মন্তব্যগুলিকে একীভূত করবেন? সমাধান 3 এখনও বিপজ্জনকভাবে ভুল।
হালকাতা রেস

@ লাইটনেসেসেসিনআরবিট আপনি কি দয়া করে একটি উত্তর সরবরাহ করতে পারেন? আপনি 2 এবং 3 এর সমাধানগুলি কেন এড়ানো এবং বিপজ্জনকভাবে ভুল বলছেন তা আমি বুঝতে পারি না।
গ্ল্যাডক্লাফ

4

প্রকৃতপক্ষে একটি স্ট্রিং ধ্রুবক আক্ষরিক না কোনও কনস্ট চর * বা চর * নয় একটি চর []। এটি বেশ অদ্ভুত তবে সি ++ নির্দিষ্টকরণে লিখিত; আপনি যদি এটি পরিবর্তন করেন তবে আচরণটি অপরিজ্ঞাত হয় কারণ সংকলক কোড সেগমেন্টে এটি সঞ্চয় করতে পারে।


5
আমি বলবো এটি কনস্ট চর [] কারণ মূল্য হিসাবে আপনি এটি পরিবর্তন করতে পারবেন না।
fnieto - ফার্নান্দো নিতো

3

আপনি এটি চেষ্টা করতে পারেন:

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

foo("Hello")

এটা আমার জন্য কাজ করে


2

কোডটির শুরুতে, কোথাও এই ম্যাক্রো যুক্ত করে আমি এই সমস্যাটি সমাধান করি solve বা এটি যোগ করুন <iostream>, hehe।

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

8
"বা <iostream>" এ কি যুক্ত করুন ?!
23-17

সেখানে ", হিহ" ছিল যে কারণেই সম্পাদিত হয়েছিল (বোঝানো হয়েছিল যে এটি একটি রসিকতা ছিল)
সোমগুয়েম্নিপি

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';: খালি । আমরা নির্দেশিত তথ্য সংশোধন করার চেষ্টা করছি। আমাদের ক্ষেত্রে এটি কোনও সংকলনের ত্রুটি সৃষ্টি করবে না, তবে একটি রানটাইম ত্রুটি ঘটায়, কারণ সম্ভবত স্ট্রিংটি সংকলিত বাইনারিটির কেবল পঠনযোগ্য বিভাগে চলে যাবে। এই বিবৃতিটি যদি আমাদের গতিশীলভাবে মেমরির বরাদ্দ করে থাকে তা অর্থপূর্ণ হবে eg 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 এবং এর বিপরীতে ব্যবহার করতে পারেন । এটি Cএকমাত্র হাতিয়ার এবং এর ফলে একচেটিয়া জিনিসগুলি (কনস্টেক্সপ্রের মতো) সমর্থন করবে না C++


0

আমিও একই সমস্যা পেয়েছি। এবং আমি যা সহজ করেছি তা কেবল চর * এর পরিবর্তে কনস্ট চর * যুক্ত করা। এবং সমস্যার সমাধান হয়েছে। অন্যরা উপরে উল্লিখিত হিসাবে এটি একটি সামঞ্জস্যপূর্ণ ত্রুটি। সি স্ট্রিংগুলিকে চর অ্যারে হিসাবে বিবেচনা করে যখন সি ++ তাদেরকে কনস্টের চর অ্যারে হিসাবে বিবেচনা করে।


0

এটির মূল্যের জন্য, আমি এই সাধারণ মোড়কের ক্লাসটি সি ++ স্ট্রিংগুলিতে রূপান্তর করার জন্য সহায়ক বলে মনে করি 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';
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.