কনস্ট চর * কনস্ট বনাম কনস্ট চর *?


110

আমি নিজেকে সি ++ এর সাথে অপরিচিত করার জন্য কয়েকটি উদাহরণস্বরূপ প্রোগ্রাম চালাচ্ছি এবং আমি নিম্নলিখিত প্রশ্নটিতে চলে এসেছি। প্রথমত, এখানে উদাহরণ কোডটি রয়েছে:

void print_string(const char * the_string)
{
    cout << the_string << endl;
}

int main () {
    print_string("What's up?");
}

উপরের কোডে, মুদ্রণ_ স্ট্রিংয়ের প্যারামিটার পরিবর্তে হতে পারে const char * const the_string। এর জন্য কোনটি সঠিক হবে?

আমি বুঝতে পারি যে পার্থক্যটি হ'ল একটি ধ্রুবক চরিত্রের জন্য একটি পয়েন্টার, অন্যটি স্থির চরিত্রের জন্য একটি স্থির পয়েন্টার। তবে কেন এই দুটোই কাজ করে? এটি কখন প্রাসঙ্গিক হবে?

উত্তর:


244

পরেরটি আপনাকে the_stringভিতরে পরিবর্তন করতে বাধা দেয় print_string। এটি আসলে এখানে উপযুক্ত হবে, তবে সম্ভবত ভারবসটি বিকাশকারীকে বন্ধ করে দিয়েছে।

char* the_string: আমি charকোন the_stringপয়েন্টগুলিতে পরিবর্তন করতে পারি এবং charএটি যেদিকে নির্দেশ করে আমি তা সংশোধন করতে পারি ।

const char* the_string: আমি charকোন the_stringপয়েন্টগুলিতে পরিবর্তন করতে পারি তবে charএটি যেদিকে নির্দেশ করে আমি তা সংশোধন করতে পারি না ।

char* const the_string: আমি charকোন the_stringপয়েন্টগুলিতে পরিবর্তন করতে পারি না তবে charএটি যেদিকে ইঙ্গিত করে তা আমি সংশোধন করতে পারি ।

const char* const the_string: আমি charকোন the_stringপয়েন্টগুলিতে পরিবর্তন করতে পারি না, বা charএটি যেদিকে নির্দেশ করে তাও আমি সংশোধন করতে পারি না ।


11
শেষ বাক্যটির জন্য +1। কনস্ট-নির্ভুলতা ভার্জোজ, তবে এটির পক্ষে ভাল।
এমএসকিফিশার

6
@ শিও: আপনার ফর্মটি আরও বিভ্রান্তিকর কারণ এটির অর্থ সম্পূর্ণরূপে পরিবর্তন করা থেকে দূরে রয়েছে। পুরোপুরি বিপরীত দিকে const char *থাকায় এটি আরও ভাল const
আর .. গীটহাব বন্ধ হেল্পিং ICE

7
@ আর ..: ঠিক আছে, কমপক্ষে আমার পক্ষেও তা না। ডান থেকে বামে পড়া, আমি "পয়েন্টার থেকে কনট চর" পাই। আমার জন্য, এটি ঠিক সেভাবেই ভাল বোধ করে।
Xeo

6
ঠিক আছে আপনি নিজেকে বোকা বানাচ্ছেন কারণ সি প্রকারগুলি ভিতরে থেকে বাইরে থেকে পড়ে থাকে, বাম থেকে ডানে না। :-)
আর .. গীটহাব বন্ধ করুন ICE

11
আমি একটু বিব্রত আমি দৃশ্যত একমাত্র ব্যক্তি যিনি এই বোঝে না নই ... কিন্তু কি হবে "গৃহস্থালির কাজ পার্থক্য করতে যা পয়েন্ট" এবং "গৃহস্থালির কাজ যা পয়েন্ট"?
অভাব

138
  1. পরিবর্তনীয় চরিত্রের জন্য পরিবর্তনীয় পয়েন্টার

    char *p;
  2. ধ্রুবক চরিত্রের জন্য পরিবর্তনীয় পয়েন্টার

    const char *p;
  3. পরিবর্তনীয় চরিত্রের জন্য নিয়মিত পয়েন্টার

    char * const p; 
  4. ধ্রুবক চরিত্রের জন্য নিয়মিত পয়েন্টার

    const char * const p;

এটি হওয়া উচিত নয়: const char* p; --> constant pointer to mutable characterএবং char *const p; --> mutable pointer to constant character
পটনিপি

2
@ নুলডপয়েন্টার নং সি ++ ডিক্লেয়ারেশনগুলি ডান থেকে বামে গঠিত হয়। আপনি এইভাবে পড়তে পারেন const char * p: "পি একটি চরিত্রের ধ্রুবকটির জন্য একটি পয়েন্টার" বা জেমস যথাযথভাবে বলেছে যে কোনও ধ্রুবক চরিত্রের জন্য একটি পরিবর্তনীয় পয়েন্টার। দ্বিতীয়টির সাথে একই :)।
সামিদামারু

28

const char * constপয়েন্টার অর্থ পাশাপাশি পয়েন্টারটি যে ডেটাটিকে নির্দেশ করে, তা উভয়ই কনস্ট!

const char *মানে পয়েন্টারটি কেবলমাত্র ডেটা বোঝায় , কনস্টেট। পয়েন্টার নিজেই তবে কনস্টেন্ট নয়।

উদাহরণ।

const char *p = "Nawaz";
p[2] = 'S'; //error, changing the const data!
p="Sarfaraz"; //okay, changing the non-const pointer. 

const char * const p = "Nawaz";
p[2] = 'S'; //error, changing the const data!
p="Sarfaraz"; //error, changing the const pointer. 

20

(আমি জানি এটি পুরানো তবে আমি যেভাবেই ভাগ করে নিতে চাই))

কেবল থমাস ম্যাথিউজের উত্তরটি বিশদভাবে জানাতে চেয়েছিলেন। সি টাইপের ঘোষণার ডান-বাম বিধিটি খুব বেশি বলে: একটি সি প্রকারের ঘোষণাপত্রটি পড়ার সময় শনাক্তকারীকে শুরু করুন এবং যখন আপনি পারবেন না তখন ডানে যান এবং যখন আপনি পারবেন না।

এটি বেশ কয়েকটি উদাহরণের সাথে সর্বোত্তমভাবে ব্যাখ্যা করা হয়েছে:

উদাহরণ 1

  • সনাক্তকারী থেকে শুরু করুন, আমরা বাম দিকে যেতে পারি তাই আমরা ডানদিকে যেতে পারি না

    const char* const foo
                ^^^^^

    ফু একটি ধ্রুবক ...

  • বাম চালিয়ে যান

    const char* const foo
              ^

    foo একটি নিয়মিত পয়েন্টার ...

  • বাম চালিয়ে যান

    const char* const foo
          ^^^^

    foo চরের একটি নিয়মিত পয়েন্টার ...

  • বাম চালিয়ে যান

    const char* const foo
    ^^^^^

    foo চর ধ্রুবক একটি ধ্রুবক পয়েন্টার (সম্পূর্ণ!)

উদাহরণ 2

  • সনাক্তকারী থেকে শুরু করুন, আমরা বাম দিকে যেতে পারি তাই আমরা ডানদিকে যেতে পারি না

    char* const foo
          ^^^^^

    ফু একটি ধ্রুবক ...

  • বাম চালিয়ে যান

    char* const foo
        ^

    foo একটি নিয়মিত পয়েন্টার ...

  • বাম চালিয়ে যান

    char* const foo
    ^^^^

    foo চরের এক ধ্রুবক পয়েন্টার (সম্পূর্ণ!)

উদাহরণ 1337

  • সনাক্তকারী থেকে শুরু করুন, কিন্তু এখন আমরা ঠিক যেতে পারি!

    const char* const* (*foo[8])()
                            ^^^

    foo 8 এর অ্যারে ...

  • হিট বন্ধনী এখন আর ডানদিকে যেতে পারে না, বাম দিকে যান go

    const char* const* (*foo[8])()
                        ^

    foo 8 টি পয়েন্টারের অ্যারে ...

  • বন্ধনী ভিতরে সমাপ্ত, এখন ডানদিকে যেতে পারেন

    const char* const* (*foo[8])()
                                ^^

    foo ফাংশন করতে 8 পয়েন্টারের একটি অ্যারে যা ফিরে আসে ...

  • ডানদিকে আর কিছুই নয়, বাম দিকে যান

    const char* const* (*foo[8])()
                     ^

    foo ফাংশন করতে 8 পয়েন্টারের একটি অ্যারে যা একটি পয়েন্টারকে একটিতে ফেরত দেয় ...

  • বাম চালিয়ে যান

    const char* const* (*foo[8])()
                ^^^^^

    foo ফাংশনগুলিতে 8 পয়েন্টারের একটি অ্যারে যা একটি পয়েন্টারকে একটি ধ্রুবককে দেয় ...

  • বাম চালিয়ে যান

    const char* const* (*foo[8])()
              ^

    foo ফাংশনগুলির জন্য 8 পয়েন্টারের একটি অ্যারে যা কোনও স্থির পয়েন্টারে একটি পয়েন্টারকে একটি স্থির করে দেয় ...

  • বাম চালিয়ে যান

    const char* const* (*foo[8])()
          ^^^^

    foo বিন্যাস ফাংশন যে একটি করার জন্য একটি ধ্রুবক পয়েন্টার একটি পয়েন্টার ফেরৎ 8 পয়েন্টার একটি অ্যারে গৃহস্থালির কাজ ...

  • বাম চালিয়ে যান

    const char* const* (*foo[8])()
    ^^^^^

    foo ফাংশনগুলির জন্য 8 পয়েন্টারের একটি অ্যারে যা একটি পয়েন্টারটিকে একটি ধ্রুবক পয়েন্টারে একটি চর ধ্রুবককে (সম্পূর্ণ!) ফেরত দেয়

আরও ব্যাখ্যা: http://www.unixwiz.net/techtips/reading-cdecl.html


সিএমআইআইডাব্লু, কনস্ট চর * কনস্ট ফু কি চর কনস্ট * কনস্ট ফু এর সমতুল্য হওয়া উচিত?
luochenhuan

@ লুচেনহুয়ান হ্যাঁ, তারা অবশ্যই আছে।
গ্যারেট

12

অনেকে ডান থেকে বামে টাইপ স্পেসিফায়ার পড়ার পরামর্শ দেন।

const char * // Pointer to a `char` that is constant, it can't be changed.
const char * const // A const pointer to const data.

উভয় ফর্মে, পয়েন্টারটি ধ্রুবক বা কেবল পঠনযোগ্য ডেটার দিকে নির্দেশ করছে।

দ্বিতীয় আকারে, পয়েন্টারটি পরিবর্তন করা যায় না; পয়েন্টারটি সর্বদা একই জায়গায় নির্দেশ করবে।


3

পার্থক্যটি হ'ল অতিরিক্ত ছাড়াই constপ্রোগ্রামারটি পরিবর্তিত হতে পারে পদ্ধতির ভিতরে, যেখানে পয়েন্টারটি নির্দেশ করে; উদাহরণ স্বরূপ:

 void print_string(const char * the_string)
 {
    cout << the_string << endl;
    //....
    the_string = another_string();
    //....

 }

স্বাক্ষর থাকলে তা পরিবর্তে অবৈধ হবে void print_string(const char * const the_string)

অনেক প্রোগ্রামার অতিরিক্ত শব্দদণ্ডটি (বেশিরভাগ পরিস্থিতিতে) অতিরিক্ত শব্দমূল অনুভব করে constএবং এটি শব্দার্থগতভাবে সঠিক হলেও এটি বাদ দেয়।


2

পরের দিকে আপনি প্রথমে পয়েন্টার এবং চরিত্র উভয়কেই সংশোধন না করার গ্যারান্টি দিচ্ছেন আপনি কেবল গ্যারান্টি দিচ্ছেন যে বিষয়বস্তু পরিবর্তন হবে না তবে আপনি পয়েন্টারটি চারদিকে সরিয়ে নিতে পারেন


আহ তাই চূড়ান্ত কনস্টেশন ছাড়া, আমি আসলে একটি সম্পূর্ণ ভিন্ন স্ট্রিং নির্দেশ করতে পয়েন্টার সেট করতে পারে?
PICT

হ্যাঁ, এই চূড়ান্ত বিন্যাস ব্যতীত আপনি পয়েন্টার গাণিতিক দ্বারা কিছু পুনরাবৃত্তি করতে প্যারামিটার পয়েন্টারটি ব্যবহার করতে পারেন, সেখানে যদি সেই কনস্ট থাকে তবে আপনাকে নিজের পয়েন্টার তৈরি করতে হবে যা সেই পরামিতির অনুলিপি।
যিশু রামোস

2

একজনের কাজ না করার কোনও কারণ নেই। সবই print_string()হল মান মুদ্রণ। এটি এটিকে সংশোধন করার চেষ্টা করে না।

ফাংশনটি তৈরি করা ভাল ধারণা যা চিহ্নের তর্কগুলি কনস্ট হিসাবে পরিবর্তন করে না। সুবিধাটি হ'ল যে ভেরিয়েবলগুলি পরিবর্তন করতে পারে না (বা আপনি পরিবর্তন করতে চান না) ত্রুটি ছাড়াই এই ফাংশনগুলিতে যেতে পারে।

যথাযথ বাক্য গঠন পর্যন্ত, আপনি নির্দেশ করতে চান যে কোন ধরণের আর্গুমেন্টটি "নিরাপদ" ফাংশনে যেতে হবে।


2

আমি মনে করি এটি খুব কমই প্রাসঙ্গিক, কারণ আপনার ফাংশনটি & * the_string বা ** the_string এর মত যুক্তি দিয়ে কল করা হচ্ছে না। পয়েন্টারটি নিজেই একটি মান-ধরণের আর্গুমেন্ট, তাই আপনি যদি এটি সংশোধন করেন তবে আপনি নিজের ফাংশনটি কল করতে ব্যবহৃত কপিটি পরিবর্তন করতে যাচ্ছেন না। আপনি যে সংস্করণটি দেখিয়েছেন তা নিশ্চিত করে যে স্ট্রিংটি পরিবর্তন হবে না এবং আমি মনে করি এটি এক্ষেত্রে যথেষ্ট।


2

const char *এর মানে হল যে আপনি যা নির্দেশ করেছেন তা পরিবর্তন করতে পয়েন্টার ব্যবহার করতে পারবেন না। যদিও আপনি পয়েন্টারটিকে অন্য কোনও কিছুতে নির্দেশ করতে পারেন তবে change

বিবেচনা:

const char * promptTextWithDefault(const char * text)
{
    if ((text == NULL) || (*text == '\0'))
        text = "C>";
    return text;
}

প্যারামিটারটি কনট চরের কোনও অবিচ্ছিন্ন পয়েন্টার, সুতরাং এটি অন্য মানতে পরিবর্তন করা যেতে পারে const char *(ধ্রুবক স্ট্রিংয়ের মতো)। তবে, যদি আমরা ভুল করে লিখি *text = '\0'তবে আমরা একটি সংকলন ত্রুটি পেতে চাই।

যুক্তিযুক্তভাবে, আপনি যদি প্যারামিটারটির দিকে ইঙ্গিত করছেন তা পরিবর্তন করতে না চান, আপনি প্যারামিটার তৈরি করতে পারেন const char * const text, তবে এটি করা সাধারণ নয়। আমরা সাধারণত ফাংশনগুলিকে প্যারামিটারগুলিতে পাস করা মানগুলি পরিবর্তন করার অনুমতি দিই (কারণ আমরা মান দ্বারা পরামিতিগুলি পাস করি, কোনও পরিবর্তন কলকারীকে প্রভাবিত করে না)।

বিটিডাব্লু: এটি এড়ানো ভাল অনুশীলন char const *কারণ এটি প্রায়শই ভুলভাবে পড়ে থাকে - এর অর্থ একই const char *, তবে অনেক লোক এটিকে অর্থ হিসাবে পড়েন char * const


কি দারুন! আমি আমার const char *এবং স্বাক্ষরের মধ্যে পার্থক্যটি সনাক্ত করার চেষ্টা করছিলাম char const *- আপনি যেভাবে আপনার বিটিডব্লিউ শব্দটি বলেছেন তা সত্যই সহায়তা করেছিল!
ঋষি

1

প্রায় অন্যান্য সমস্ত উত্তর সঠিক, তবে সেগুলির একটি দিক মিস করে: আপনি যখন constকোনও ফাংশন ঘোষণায় কোনও পরামিতি অতিরিক্ত ব্যবহার করেন , সংকলকটি এটিকে অবশ্যই অগ্রাহ্য করবে। এক মুহুর্তের জন্য আসুন, আপনার উদাহরণের পয়েন্টার হওয়ার জটিলতা উপেক্ষা করুন এবং কেবলমাত্র একটি ব্যবহার করুন int

void foo(const int x);

হিসাবে একই ফাংশন ঘোষণা

void foo(int x);

শুধুমাত্র ফাংশনটির সংজ্ঞাটিতে অতিরিক্ত constঅর্থবোধক:

void foo(const int x) {
    // do something with x here, but you cannot change it
}

এই সংজ্ঞাটি উপরের যে কোনও ঘোষণার সাথে সামঞ্জস্যপূর্ণ। আহ্বানকারী গ্রাহ্য না করে যে xহয় const--that একটি বাস্তবায়ন বিস্তারিত যে কল সাইট এ প্রাসঙ্গিক নন।

আপনার যদি ডেটাতে constপয়েন্টার থাকে constতবে একই বিধিগুলি প্রয়োগ হয়:

// these declarations are equivalent
void print_string(const char * const the_string);
void print_string(const char * the_string);

// In this definition, you cannot change the value of the pointer within the
// body of the function.  It's essentially a const local variable.
void print_string(const char * const the_string) {
    cout << the_string << endl;
    the_string = nullptr;  // COMPILER ERROR HERE
}

// In this definition, you can change the value of the pointer (but you 
// still can't change the data it's pointed to).  And even if you change
// the_string, that has no effect outside this function.
void print_string(const char * the_string) {
    cout << the_string << endl;
    the_string = nullptr;  // OK, but not observable outside this func
}

কিছু সি ++ প্রোগ্রামার constপ্যারামিটারগুলি পয়েন্টার কিনা তা বিবেচনা না করে প্যারামিটারগুলি তৈরি করতে বিরক্ত করে ।


"সংকলকটি মূলত এটিকে উপেক্ষা করবে" সর্বদা সত্য নয়, ভিজ্যুয়াল সি ++ 2015 সতর্কতা তৈরি করে যদি আপনি constসংজ্ঞা হিসাবে আপনার ফাংশন প্যারামিটারে অতিরিক্ত যোগ করেন তবে ঘোষণা না করে।
raymai97

@ রায়মাই 77: আমি মনে করি এটি 2015 সংকলকটিতে একটি বাগ, তবে আমার কাছে 2015 পরীক্ষা করার সুযোগ নেই। আমি 2017 সালে বর্ণিত হিসাবে কাজ করি, যা কিছু মান বিশেষজ্ঞের সাথে আমার কথোপকথন অনুসারে প্রত্যাশিত আচরণ।
অ্যাড্রিয়ান ম্যাকার্থি

-1

উভয়ের মধ্যে পার্থক্য হ'ল চর * যে কোনও নির্বিচারে পয়েন্টারকে নির্দেশ করতে পারে। বিপরীতে কনস্ট চর *, এক্সিকিউটেবলের ডেটা বিভাগে সংজ্ঞায়িত ধ্রুবকগুলিকে নির্দেশ করে। এবং এর মতো, আপনি কনস্ট চর * স্ট্রিংয়ের চরিত্রের মানগুলি পরিবর্তন করতে পারবেন না।


আমি চর * এবং কনস্ট চর * এর মধ্যে পার্থক্য জিজ্ঞাসা করছি না। আমি const গৃহস্থালি মধ্যে জিজ্ঞেস করছি * এবং const গৃহস্থালি * const
PICT

এই উত্তরটি ভুল। একজন const char*যে কোন জায়গায় বাতলান তা বাছাই করে নিয়েছেন।
কিউবিক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.