কনস্ট ইন্ট *, কনস্ট ইন্ট * কনস্ট এবং ইনস্ট কনস্ট * এর মধ্যে পার্থক্য কী?


1354

আমি সবসময় কিভাবে ব্যবহার করতে আপ জগাখিচুড়ি const int*, const int * constএবং int const *সঠিকভাবে। আপনি যা করতে পারেন এবং কী করতে পারবেন না তার সংজ্ঞা দেওয়ার কোনও বিধি রয়েছে?

অ্যাসাইনমেন্টের ক্ষেত্রে, কাজগুলিতে পাস করা ইত্যাদির ক্ষেত্রে আমি সমস্ত করণীয় এবং সমস্ত কাজগুলি কী তা জানতে চাই


175
আপনি বেশিরভাগ সি এবং সি ++ ডিকোলেমিশনটি বোঝার জন্য "ক্লকওয়াইজ / সর্পিল বিধি" ব্যবহার করতে পারেন ।
জেমস ম্যাকনেলিস

52
cdecl.org একটি দুর্দান্ত ওয়েবসাইট যা আপনার জন্য সি ঘোষণার স্বয়ংক্রিয় অনুবাদ করে।
ডেভ গালাগার

6
@Calmarius: , শুরু যেখানে টাইপ-নাম / হওয়া উচিত পদক্ষেপ অধিকার যখন আপনি, বাম যখন আপনাকে অবশ্যইint *(*)(char const * const)। ডানদিকে শুরুর আলাদা *তারপর আমরা বামে সরে গিয়ে করতে হবে: pointer। ডান বন্ধনী বাইরে, আমরা ঠিক স্থানান্তর করতে পারেন: pointer to function of ...। তারপর আমরা বাম সরাতে আছে: pointer to function of ... that returns pointer to int। প্যারামিটার (প্রসারিত করতে একই পদ্ধতি পুনরাবৃত্তি করুন ...): pointer to function of (constant pointer to constant char) that returns pointer to int। পাসকালের মতো সহজ-পাঠ্য ভাষায় সমতুল্য এক-লাইন ঘোষণার কী হবে?
মার্ক কে কোয়ান

1
@MarkKCowan সালে পাসকাল এটা ভালো কিছু হবে function(x:^char):^int। ফাংশনের ধরণগুলি কোনও ফাংশনের প্রতি নির্দেশক থাকে তাই এটি নির্দিষ্ট করার দরকার নেই এবং পাস্কাল কনস্টের যথার্থতা প্রয়োগ করে না। এটি বাম থেকে ডানে পড়তে পারে।
কলমারিয়াস

5
"কনস্ট" এর বামে প্রথম জিনিসটি ধ্রুবকটি। যদি "কনস্ট্যান্ট" জিনিসটি বামদিকে সবচেয়ে দূরে থাকে তবে তার ডানদিকে প্রথম জিনিসটি ধ্রুবকটি।
কাপকেক

উত্তর:


2205

এটি পিছনের দিকে পড়ুন ( ক্লকওয়াইজ / সর্পিল বিধি দ্বারা চালিত ):

  • int* - ইনটার পয়েন্টার
  • int const * - পয়েন্টার থেকে কনট ইনট
  • int * const - অন্তর্নির্মিত পয়েন্টার বিন্দু
  • int const * const - কনস্ট পয়েন্টার থেকে কনট ইনট

এখন প্রথম constটাইপের উভয় পাশে থাকতে পারে:

  • const int * == int const *
  • const int * const == int const * const

আপনি যদি সত্যিই পাগল হতে চান তবে আপনি এই জাতীয় জিনিসগুলি করতে পারেন:

  • int ** - পয়েন্টার থেকে ইন্টি পয়েন্টার
  • int ** const - একটি ইন্টি পয়েন্টারে একটি কনস্ট পয়েন্টার
  • int * const * - একটি অন্তর্নিহিত পয়েন্টার একটি পয়েন্টার
  • int const ** - একটি বিন্দু বিন্দুতে একটি পয়েন্টার একটি পয়েন্টার
  • int * const * const - একটি অন্তর্গঠিত পয়েন্টার একটি কনস্ট পয়েন্টার
  • ...

এবং এটি নিশ্চিত করার জন্য যে আমরা এর অর্থ সম্পর্কে পরিষ্কার const:

int a = 5, b = 10, c = 15;

const int* foo;     // pointer to constant int.
foo = &a;           // assignment to where foo points to.

/* dummy statement*/
*foo = 6;           // the value of a can´t get changed through the pointer.

foo = &b;           // the pointer foo can be changed.



int *const bar = &c;  // constant pointer to int 
                      // note, you actually need to set the pointer 
                      // here because you can't change it later ;)

*bar = 16;            // the value of c can be changed through the pointer.    

/* dummy statement*/
bar = &a;             // not possible because bar is a constant pointer.           

fooধ্রুবক পূর্ণসংখ্যার জন্য একটি পরিবর্তনশীল পয়েন্টার। এটি আপনাকে নির্দেশিত মান পরিবর্তন করতে দেয় তবে আপনি যে মানটিকে নির্দেশ করেন তা নয়। প্রায়শই এটি সি-স্টাইলের স্ট্রিংগুলির সাথে দেখা যায় যেখানে আপনার a এর পয়েন্টার রয়েছে const char। আপনি কোন স্ট্রিংকে নির্দেশ করেছেন তা আপনি পরিবর্তন করতে পারেন তবে আপনি এই স্ট্রিংয়ের সামগ্রী পরিবর্তন করতে পারবেন না। এটি গুরুত্বপূর্ণ যখন স্ট্রিং নিজেই কোনও প্রোগ্রামের ডেটা বিভাগে থাকে এবং পরিবর্তন করা উচিত নয়।

barএকটি মানের একটি ধ্রুবক বা স্থির পয়েন্টার যা পরিবর্তিত হতে পারে। এটি অতিরিক্ত সিনট্যাকটিক চিনি ছাড়াই একটি রেফারেন্সের মতো। এই সত্যের কারণেই, আপনি সাধারণত একটি রেফারেন্স ব্যবহার করতেন যেখানে আপনি T* constপয়েন্টার ব্যবহারের প্রয়োজন না হলে আপনি পয়েন্টার ব্যবহার করবেন NULL


480
আমি থাম্বের একটি নিয়ম সংযোজন করতে চাই যা আপনাকে কীভাবে 'কনস্ট' পয়েন্টার বা পয়েন্টেড ডেটার ক্ষেত্রে প্রযোজ্য তা আবিষ্কার করতে সাহায্য করতে পারে: অ্যাসিটারিক্স চিহ্নে বিবৃতিটি বিভক্ত করুন, তবে কনস্ট কীওয়ার্ডটি যদি বাম অংশে প্রদর্শিত হয় (যেমন 'কনট ইনট * ফু') - এটি সঠিক পয়েন্টের সাথে সম্পর্কিত, যদি এটি ডান অংশে থাকে ('ইনট * কনস্ট বার') - এটি পয়েন্টারটির বিষয়ে।
মাইকেল

14
@ মিশেল: কনস্ট নিয়ম মনে রাখার / বোঝার জন্য এই জাতীয় সরল নিয়মের জন্য মাইকেলকে কুডোস।
শিববধু

10
@ জেফ্রি: পিছন দিকে পড়ুন যতক্ষণ প্যারেনেসিস নেই ততক্ষণ কাজ করে। তারপরে, ভাল ...
টাইপডেফগুলি

12
+1, যদিও আরও ভাল সংক্ষিপ্তসারটি হ'ল: পিছনে পয়েন্টার ঘোষণাপত্রগুলি পড়ুন , এর অর্থ, @ মিশেলের বক্তব্যটির নিকটবর্তী: প্রথম তারকাটিতে স্বাভাবিক বাম থেকে ডানদিকে পড়া বন্ধ করুন ।
ওল্ফ

3
@ গেডমিয়াল এটি করে, এটি দুর্দান্ত কাজ করে, তবে আপনাকে অবশ্যই এটি ঘোষণার সাথে সাথে এটি নির্ধারণ করতে হবে (কারণ আপনি "কনস্ট পয়েন্টার" পুনরায় সাইন করতে পারবেন না)। const int x = 0; const int *const px = &x; const int *const *const p = &px;ঠিক কাজ করে।
রাস্তাজেদি

356

যারা ক্লকওয়াইজ / সর্পিল বিধি সম্পর্কে জানেন না: ভেরিয়েবলের নাম থেকে শুরু করুন, ঘড়ির কাঁটার দিক থেকে এগিয়ে যান (এই ক্ষেত্রে পিছনে সরান) পরবর্তী পয়েন্টার বা টাইপ করুন । ভাব শেষ না হওয়া পর্যন্ত পুনরাবৃত্তি করুন।

এখানে একটি ডেমো রয়েছে:

ইনটার পয়েন্টার

বিন্যাস পয়েন্টার ইন ইন কনট

পয়েন্টার ইন ইন কনট

পয়েন্টার থেকে কনট ইনট

অন্তর্নির্মিত পয়েন্টার


8
@ জ্যান জটিল লিঙ্কের লিঙ্কটির অনুমতি নেই। আপনি কি এখানে সরাসরি পোস্ট করতে পারেন, বা দেখার সীমাবদ্ধতাগুলি সরাতে পারেন?
R71

8
@ রোগ এটির সমস্ত উন্মুক্ত অ্যাক্সেস অনুমতি ব্যবহার করত ... দুর্ভাগ্যক্রমে আমি নিবন্ধটি লিখিনি এবং অ্যাক্সেসের অনুমতিও নেই। যাইহোক, এখানে নিবন্ধটির একটি সংরক্ষণাগারিত সংস্করণ রয়েছে যা এখনও কাজ করে: সংরক্ষণাগার.আইস / এসএসএমএমএক্স
জানু রেগেগ

8
জটিল উদাহরণটি এখনও ডান থেকে বামে রয়েছে তবে এর মধ্যে প্রথম বন্ধনীগুলি যেমন সমাধান করা হয় ঠিক তেমন সমাধান করে। পুরো ঘড়ির কাঁটার সর্পিল জিনিসটি কোনও সহজ করে না।
ম্যাথু

4
চূড়ান্ত উদাহরণ: void (*signal(int, void (*fp)(int)))(int);আর্কাইভ.আইএস
এসএসএমএমএক্স

3
এই নিয়মের উপর নির্ভর করবেন না। এটি সর্বজনীন নয়। এটি ব্যর্থ কিছু ক্ষেত্রে আছে।
হ্যাকগুলি

150

আমি মনে করি এখানে ইতিমধ্যে সমস্ত কিছুর উত্তর দেওয়া হয়েছে, তবে আমি কেবল এটি যুক্ত করতে চাই যে আপনার উচিত সাবধান typedef! তারা কেবল পাঠ্য প্রতিস্থাপন নয়।

উদাহরণ স্বরূপ:

typedef char *ASTRING;
const ASTRING astring;

ধরণ astringহয় char * constনা const char *। আমি সর্বদা constটাইপের ডানদিকে রাখার ঝোঁক রাখার এই একটি কারণ , এবং কখনই শুরুতে নয়।


20
এবং আমার জন্য এটি টাইপেফ পয়েন্টারগুলির কারণ নয়। আমি এই জাতীয় কিছুতে সুবিধা দেখতে পাচ্ছি না typedef int* PINT(আমি এটির কিছু অনুমান করি যা সি এর অনুশীলন থেকে এসেছে এবং অনেক বিকাশকারী এটি করে চলেছেন)। দুর্দান্ত, আমি এটির *সাথে একটি প্রতিস্থাপন করেছি P, এটি টাইপিংকে গতি দেয় না, আপনার উল্লেখ করা সমস্যাটি প্রবর্তন করে।
মাফানে

1
@ মাফানে - আমি এটি দেখতে পারি। যাইহোক, আমার কাছে ব্যতিক্রমী সিনট্যাকটিক নিয়মটি এড়িয়ে চলার পরিবর্তে ব্যতিক্রমী সিনট্যাকটিকাল নিয়মটি ব্যবহার না করার পরিবর্তে একটি দুর্দান্ত ভাষার বৈশিষ্ট্য এড়াতে পিছনের দিকের মতো বলে মনে হচ্ছে যাতে আপনি নিরাপদে এই ভাষার বৈশিষ্ট্যটি ব্যবহার করতে পারেন ।
টেড

6
@ মেফেন PINTপ্রকৃতপক্ষে টাইপইফের পরিবর্তে বোবা ব্যবহার, বিশেষত এটি আমার মনে করে যে সিস্টেম স্টোরগুলি মেমরির জন্য বিয়ার ব্যবহার করে। টাইপডিফ গুলি পয়েন্টারগুলি ফাংশনগুলির সাথে ডিল করার জন্য বেশ কার্যকর are
ApproachingDarknessFish

5
@ কাজড্রেগন ধন্যবাদ! তা ছাড়া, আমি সমস্ত typedefed সঙ্গে বিশৃঙ্খলার সৃষ্টি করেছি হবে PVOID, LPTSTRWin32 API এ কাপড়!
ডেভিড লি

2
@ মেফেন: নির্দিষ্ট লিগ্যাসি ম্যাক্রোগুলি ব্যবহার করার সময় আমাকে কয়েকবার পিছু কিছু ব্যবহার করতে হয়েছিল যা টাইপ গ্রহণ করার জন্য লেখা ছিল, তবে টাইপটি যদি একক বর্ণানুক্রমিক শনাক্তকারী না হয় তবে বিচ্ছিন্ন হয়ে যেত। :)
গ্রু

56

বেশিরভাগের মতো সবাই নির্দেশ করেছে:

মধ্যে পার্থক্য কি const X* p, X* const pএবং const X* const p?

আপনাকে পয়েন্টার ঘোষণাগুলি ডান থেকে বামে পড়তে হবে।

  • const X* p এর অর্থ "পি বিন্দুতে থাকা একটি এক্সকে নির্দেশ করে": এক্স অবজেক্ট পি এর মাধ্যমে পরিবর্তন করা যায় না।

  • X* const p "পি একটি এক্স এর একটি কনস্ট পয়েন্টার যা নন-কনস্ট্যান্ট": আপনি পয়েন্টার পি নিজেই পরিবর্তন করতে পারবেন না, তবে আপনি পি এর মাধ্যমে এক্স অবজেক্ট পরিবর্তন করতে পারবেন।

  • const X* const p এর অর্থ "পি একটি এক্সের কাছে একটি কনস্টিক পয়েন্টার যা কনস্ট্যান্ট": আপনি পয়েন্টার পি নিজেই পরিবর্তন করতে পারবেন না, আপনি পি এর মাধ্যমে এক্স অবজেক্টও পরিবর্তন করতে পারবেন না।


3
এটি ভুলে যাবেন না const X* p;== X const * p;হিসাবে"p points to an X that is const": the X object can't be changed via p.
জেসি চিশলম

সহজ এবং সুন্দর ব্যাখ্যা!
এডিসন লো

50
  1. অবিচ্ছিন্ন রেফারেন্স:

    একটি চলক (এখানে int) একটি রেফারেন্স, যা ধ্রুবক। আমরা ভেরিয়েবলটিকে মূলত একটি রেফারেন্স হিসাবে পাস করি, কারণ রেফারেন্সগুলি প্রকৃত মানের তুলনায় আকারে ছোট, তবে এর একটি পার্শ্ব প্রতিক্রিয়া রয়েছে এবং এটি কারণ এটি আসল ভেরিয়েবলের একটি উপামের মতো। আমরা দুর্ঘটনাবশত পুরো নামটি আমাদের অ্যাক্সেসের মাধ্যমে মূল পরিবর্তনশীলটি পরিবর্তন করতে পারি, তাই আমরা এই পার্শ্ব প্রতিক্রিয়াটিকে রোধ করার জন্য এটি স্থির করে তুলি।

    int var0 = 0;
    const int &ptr1 = var0;
    ptr1 = 8; // Error
    var0 = 6; // OK
  2. ধ্রুব পয়েন্টার

    একবার ধ্রুবক পয়েন্টারটি একটি ভেরিয়েবলের দিকে নির্দেশ করে তবে এটি অন্য কোনও চলককে নির্দেশ করতে পারে না।

    int var1 = 1;
    int var2 = 0;
    
    int *const ptr2 = &var1;
    ptr2 = &var2; // Error
  3. স্থির পয়েন্টার

    যে পয়েন্টারটির মাধ্যমে কেউ কোনও পয়েন্টের পরিবর্তকের মান পরিবর্তন করতে পারে না তা স্থির হিসাবে পয়েন্টার হিসাবে পরিচিত।

    int const * ptr3 = &var2;
    *ptr3 = 4; // Error
  4. একটি ধ্রুবকের কাছে নিয়মিত পয়েন্টার ter

    একটি ধ্রুবকের কাছে ধ্রুবক পয়েন্টার হ'ল একটি পয়েন্টার যা এটি দেখানো ঠিকানা পরিবর্তন করতে পারে না এবং এটি ঠিকানায় রাখা মান পরিবর্তন করতে পারে না।

    int var3 = 0;
    int var4 = 0;
    const int * const ptr4 = &var3;
    *ptr4 = 1;     // Error
     ptr4 = &var4; // Error

20

সাধারণ নিয়মটি হ'ল constকীওয়ার্ডটি তত্ক্ষণাত্ এর আগে যা ঘটে তার প্রযোজ্য। ব্যতিক্রম, একটি সূচনা constনিম্নলিখিতগুলির জন্য প্রযোজ্য।

  • const int*একই int const*এবং এর অর্থ "ধ্রুবক ইন পয়েন্টার"
  • const int* constহিসাবে একই int const* constএবং "ধ্রুবক ইন ধ্রুবক পয়েন্টার" মানে ।

সম্পাদনা: করণীয় ও করণীয়দের জন্য, যদি এই উত্তরটি যথেষ্ট না হয়, আপনি কী চান সে সম্পর্কে আপনি আরও সুনির্দিষ্ট হতে পারেন?


19

এই প্রশ্নটি সঠিকভাবে দেখায় যে আমি আমার প্রশ্নে যেভাবে উল্লেখ করেছি তা টাইপ আইডি গ্রহণের পরে কনস্টের মতো কেন করতে পছন্দ করি ?

সংক্ষেপে, আমি নিয়মটি মনে রাখার সবচেয়ে সহজ উপায়টি হ'ল "কনস্ট" যে জিনিসটি প্রয়োগ হয় তার পরে চলে after সুতরাং আপনার প্রশ্নে, "ইনট কনস্ট *" এর অর্থ হ'ল ইনট ধ্রুবক, যখন "ইনট * কনস্ট" এর অর্থ পয়েন্টারটি ধ্রুবক।

যদি কেউ এটিকে একেবারে সামনে রাখার সিদ্ধান্ত নেন (যেমন: "কনস্ট ইনট *"), এক্ষেত্রে বিশেষ ব্যতিক্রম হিসাবে এটি তার পরে জিনিসটির জন্য প্রযোজ্য।

অনেক লোক এই বিশেষ ব্যতিক্রমটি ব্যবহার করতে পছন্দ করেন কারণ তারা মনে করেন এটি আরও সুন্দর দেখাচ্ছে। আমি এটিকে অপছন্দ করি, কারণ এটি ব্যতিক্রম thus


2
আমি এই ইস্যুতে ছেঁড়া যৌক্তিকভাবে এটি বোধগম্য হয়। তবে বেশিরভাগ সি ++ বিকাশকারীরা লিখতেন const T*এবং এটি আরও প্রাকৃতিক হয়ে উঠেছে। আপনি যেভাবে T* constযে কোনও উপায়ে কখনই ব্যবহার করেন না , সাধারণত একটি রেফারেন্স ঠিক ঠিক করে দেবে। আমি এগুলি একবার পেয়েছিলাম যখন একবার চেয়েছিলাম boost::shared_ptr<const T>এবং পরিবর্তে লিখেছিলাম const boost::shared_ptr<T>। কিছুটা ভিন্ন প্রসঙ্গে একই সমস্যা।
ম্যাট দাম

প্রকৃতপক্ষে, আমি ধ্রুবকগুলির তুলনায় আমি প্রায়শই স্থির পয়েন্টার ব্যবহার করি। এছাড়াও, আপনাকে কীভাবে পয়েন্টারগুলিতে পয়েন্টারগুলির উপস্থিতিতে প্রতিক্রিয়া বলতে চলেছেন সে সম্পর্কেও আপনাকে ভাবতে হবে (ইত্যাদি) স্বীকার করুন যে সেগুলি বিরল, তবে আপনি এমন পরিস্থিতিগুলি এমনভাবে ভাবতে পারেন যাতে আপনি এই পরিস্থিতিগুলিকে অ্যাপলম্ব দিয়ে পরিচালনা করতে পারেন।
টেড

1
টাইপের ডানদিকে কনস্ট স্থাপনের অন্য একটি দুর্দান্ত সুবিধা হ'ল এখন যে কোনওটির বামে সমস্ত constকিছু কনস্টের টাইপ এবং তার ডানদিকে সবকিছুই যা আসলে কনস্ট হয়। int const * const * p;উদাহরণ হিসাবে নিন । না আমি সাধারণত এটি লিখি না, এটি কেবল একটি উদাহরণ। প্রথম const: টাইপ int-, এবং int- এ const হয় const পয়েন্টার বিষয়বস্তু যে বিষয়বস্তু যে p। দ্বিতীয় কনস্ট: টাইপটি constইন্টি টু পয়েন্টার , কনস্ট ওবলেক্টের বিষয়বস্তু p
হ'ল

18

এর সাধারণ ব্যবহার const

সবচেয়ে সহজ ব্যবহার হ'ল নাম ধ্রুবক ঘোষণা করা declare এটি করার জন্য, কেউ একটি ধ্রুবককে ঘোষনা করে যেন এটি একটি পরিবর্তনশীল তবে তার constআগে যোগ করুন । একে একে কনস্ট্রাক্টরের সাথে সাথেই শুরু করতে হবে কারণ অবশ্যই এটি পরে মান নির্ধারণ করতে পারে না যে এটির পরিবর্তন হবে। উদাহরণ স্বরূপ:

const int Constant1=96; 

Constant196 মান সহ একটি পূর্ণসংখ্যক ধ্রুবক তৈরি করবে, অকল্পনীয়ভাবে ডাকা হবে ।

এই ধরণের ধ্রুবকগুলি পরামিতিগুলির জন্য দরকারী যা প্রোগ্রামে ব্যবহৃত হয় তবে প্রোগ্রামটি সংকলিত হওয়ার পরে তাদের পরিবর্তন করার প্রয়োজন হয় না। এটি সি প্রিপ্রোসেসর #defineকমান্ডের উপর প্রোগ্রামারদের পক্ষে একটি সুবিধা রয়েছে যে এটি সংকলক নিজেই বুঝতে পেরেছেন এবং ব্যবহার করেছেন, মূল সংকলকটিতে পৌঁছানোর আগে কেবল প্রিপ্রসেসর দ্বারা প্রোগ্রামের পাঠ্যে প্রতিস্থাপন করা হয় না, সুতরাং ত্রুটি বার্তাগুলি আরও বেশি সহায়ক।

এটি পয়েন্টারগুলির সাথেও কাজ করে তবে constপয়েন্টারটি কী নির্দেশ করে বা এটি কোনটি ধ্রুবক বা উভয় তা নির্ধারণ করতে হবে সেদিকে সতর্কতা অবলম্বন করতে হবে । উদাহরণ স্বরূপ:

const int * Constant2 

Constant2একটি ধ্রুবক পূর্ণসংখ্যার জন্য পরিবর্তনশীল পয়েন্টার এবং এটি ঘোষণা করে :

int const * Constant2

একটি বিকল্প বাক্য গঠন যা একই কাজ করে whereas

int * const Constant3

ঘোষণা করে যে Constant3একটি পরিবর্তনশীল পূর্ণসংখ্যার এবং ধ্রুবক পয়েন্টার হয়

int const * const Constant4

Constant4স্থির পূর্ণসংখ্যার জন্য ধ্রুবক পয়েন্টার হিসাবে ঘোষণা করে । মূলত 'কনস্ট' তার তাত্ক্ষণিক বাম দিকে যা আছে তার জন্য প্রযোজ্য (এটির কিছুক্ষণ যদি তা না থাকে তবে এটি তার ডানদিকের ডানদিকে যা প্রয়োগ করে)।

রেফ: http://duramecho.com/ComputerInifications/WHHowCppConst.html


9

আমি সি ++ গুরু স্কট মায়ার্সের এই বইটি না আসা পর্যন্ত আপনার মত সন্দেহ ছিল । এই বইয়ের তৃতীয় আইটেমটি উল্লেখ করুন যেখানে তিনি ব্যবহার সম্পর্কে বিশদ আলোচনা করেছেন const

শুধু এই পরামর্শ অনুসরণ করুন

  1. শব্দটি যদি constনক্ষত্রের বাম দিকে উপস্থিত হয়, তবে যা নির্দেশিত তা ধ্রুবক
  2. যদি শব্দটি constনক্ষত্রের ডানদিকে প্রদর্শিত হয় তবে পয়েন্টারটি নিজেই ধ্রুবক
  3. যদি constউভয় পক্ষ প্রদর্শিত হয়, উভয় ধ্রুবক

7

এটা সহজ কিন্তু কৌতুকপূর্ণ। দয়া করে মনে রাখবেন যে আমরা যে constকোনও ডেটা টাইপের ( intবা char,float , ইত্যাদি)।

আসুন নীচের উদাহরণগুলি দেখুন।


const int *p==> *pকেবল পঠনযোগ্য [ pএকটি ধ্রুবক পূর্ণসংখ্যার পয়েন্টার]

int const *p==> *pকেবল পঠনযোগ্য [ pএকটি ধ্রুবক পূর্ণসংখ্যার পয়েন্টার]


int *p const==> ভুল বক্তব্য। সংকলক একটি সিনট্যাক্স ত্রুটি ছুড়ে ফেলে।

int *const p==> pকেবল পঠনযোগ্য [ pএকটি পূর্ণসংখ্যার জন্য ধ্রুবক পয়েন্টার]। pএখানে পয়েন্টারটি কেবল পঠনযোগ্য হিসাবে ঘোষণা এবং সংজ্ঞা একই জায়গায় হওয়া উচিত।


const int *p const ==> ভুল বক্তব্য। সংকলক একটি সিনট্যাক্স ত্রুটি ছুড়ে ফেলে।

const int const *p ==> *pকেবল পঠনযোগ্য

const int *const p1 ==> *pএবং pকেবল পঠনযোগ্য [ pএকটি ধ্রুবক পূর্ণসংখ্যার একটি ধ্রুবক পয়েন্টার]। pএখানে পয়েন্টারটি কেবল পঠনযোগ্য হিসাবে ঘোষণা এবং সংজ্ঞা একই জায়গায় হওয়া উচিত।


int const *p const ==> ভুল বক্তব্য। সংকলক একটি সিনট্যাক্স ত্রুটি ছুড়ে ফেলে।

int const int *p ==> ভুল বক্তব্য। সংকলক একটি সিনট্যাক্স ত্রুটি ছুড়ে ফেলে।

int const const *p ==> *pকেবল পঠনযোগ্য এবং সমানint const *p

int const *const p ==> *pএবং pকেবল পঠনযোগ্য [ pএকটি ধ্রুবক পূর্ণসংখ্যার একটি ধ্রুবক পয়েন্টার]। pএখানে পয়েন্টারটি কেবল পঠনযোগ্য হিসাবে ঘোষণা এবং সংজ্ঞা একই জায়গায় হওয়া উচিত।


6

সি ++ তে কনস্টের সঠিকতার আশেপাশে রয়েছে আরও অনেক সূক্ষ্ম পয়েন্ট। আমি মনে করি এখানে প্রশ্নটি কেবল সি সম্পর্কে হয়েছে তবে ট্যাগটি সি ++ হওয়ায় আমি কিছু সম্পর্কিত উদাহরণ দেব:

  • আপনি প্রায়শই স্ট্রিংয়ের মতো বৃহত যুক্তিগুলি পাস করেন TYPE const &যা বস্তুটিকে পরিবর্তন বা অনুলিপি করা থেকে বাধা দেয়। উদাহরণ:

    TYPE& TYPE::operator=(const TYPE &rhs) { ... return *this; }

    তবে TYPE & constঅর্থহীন কারণ কারণ উল্লেখগুলি সর্বদা নিরপেক্ষ থাকে।

  • আপনার সর্বদা শ্রেণীর পদ্ধতিগুলি লেবেল করা উচিত যা শ্রেণিটিকে যেমন পরিবর্তন করে না const, অন্যথায় আপনি কোনও TYPE const &রেফারেন্স থেকে পদ্ধতিটি কল করতে পারবেন না । উদাহরণ:

    bool TYPE::operator==(const TYPE &rhs) const { ... }

  • এমন সাধারণ পরিস্থিতি রয়েছে যেখানে রিটার্নের মান এবং পদ্ধতি উভয়ই স্থির হওয়া উচিত। উদাহরণ:

    const TYPE TYPE::operator+(const TYPE &rhs) const { ... }

    প্রকৃতপক্ষে, কনস্টের পদ্ধতিগুলি অবশ্যই অভ্যন্তরীণ শ্রেণীর ডেটা রেফারেন্স-টু অ-কনস্টেরেন্ট হিসাবে ফেরত দেবে না।

  • ফলস্বরূপ, একজনকে প্রায়শই কনট ওভারলোডিং ব্যবহার করে একটি কনস্ট এবং একটি নন-কনস্ট্যান্ড পদ্ধতি উভয়ই তৈরি করতে হবে। উদাহরণস্বরূপ, আপনি যদি সংজ্ঞা দেন T const& operator[] (unsigned i) const;তবে আপনি সম্ভবত নন-কনস্ট্যান্ট সংস্করণটিও চাইবেন:

    inline T& operator[] (unsigned i) { return const_cast<char&>( static_cast<const TYPE&>(*this)[](i) ); }

আফাক, সি তে কোন কনস্ট্যান্ড ফাংশন নেই, অ-সদস্য ফাংশনগুলি নিজেরাই সি ++ এ কনস্টেট থাকতে পারে না, কনস্টের পদ্ধতিগুলির পার্শ্ব প্রতিক্রিয়া থাকতে পারে এবং সংকলক সদৃশ ফাংশন কলগুলি এড়াতে কনস্ট্যান্ড ফাংশনগুলি ব্যবহার করতে পারে না। প্রকৃতপক্ষে, এমনকি একটি সাধারণ int const &রেফারেন্সও সেই মানটি প্রত্যক্ষ করতে পারে যা এটি অন্য কোথাও পরিবর্তিত হতে পারে।


6

সি এবং সি ++ ডিক্লেয়ারেশন সিনট্যাক্সটি বারবার মূল ডিজাইনারদের দ্বারা একটি ব্যর্থ পরীক্ষা হিসাবে বর্ণনা করা হয়েছে।

পরিবর্তে, যাক "পয়েন্টার টু " টাইপটির নাম দিন Type; আমি এটি কল করব Ptr_:

template< class Type >
using Ptr_ = Type*;

এখন Ptr_<char>একটি পয়েন্টার char

Ptr_<const char>একটি পয়েন্টার const char

এবং const Ptr_<const char>একটি constপয়েন্টার const char

সেখানে।

এখানে চিত্র বর্ণনা লিখুন


3
আপনার প্রথম বাক্যটির জন্য একটি উদ্ধৃতি আছে?
sp2danny

@ স্প2ডান্নি: গুগলিং "সি সিনট্যাক্স ব্যর্থ পরীক্ষা" কেবল বাজনার স্ট্রস্ট্রপের সাথে বেশ কয়েকটি সাক্ষাত্কারে কাশি খেয়েছিল যেখানে তিনি সেদিকে তার মতামত প্রকাশ করেছেন , যেমন স্ল্যাশডট সাক্ষাত্কারে "আমি সি ডিক্লেয়ার সিনট্যাক্সকে একটি ব্যর্থতা পরীক্ষা বলে বিবেচনা করি"। সুতরাং সি এর মূল ডিজাইনারদের দৃষ্টিভঙ্গি সম্পর্কে দাবির বিষয়ে আমার কাছে কোনও রেফারেন্স নেই, আমার ধারণা এটি যথেষ্ট শক্তিশালী গবেষণা প্রচেষ্টা দ্বারা পাওয়া যেতে পারে, বা কেবল তাদের জিজ্ঞাসা করে অস্বীকার করা যেতে পারে তবে আমি মনে করি এটি এখনকার মতো আরও ভাল। দাবির সেই অংশটি সহ, এখনও অনিশ্চিত এবং সম্ভবত সত্য :)
চিয়ার্স এবং এইচটিএস। - Alf

1
"সি এবং সি ++ ডিক্লেয়ারেশন সিনট্যাক্সটি বারবার মূল ডিজাইনারদের দ্বারা একটি ব্যর্থ পরীক্ষা হিসাবে বর্ণনা করা হয়েছে।" সি এর জন্য ভুল দয়া করে সি সম্পর্কে আপনার বাক্য পরিবর্তন করুন বা কিছু উদ্ধৃতি সরবরাহ করুন।
স্টারগেটর

3
@ স্টারগেটর: সম্ভবত আপনি পূর্ববর্তী মন্তব্যগুলি পড়েছেন এবং এমন কিছু খুঁজে পেয়েছেন যা আপনি পেডেন্টরির জন্য লাভ করতে পারেন। আপনার জীবনের জন্য শুভকামনা। যাইহোক, আমার মতো পুরনো টাইমাররা অনেক কিছুই মনে রাখে যা আমরা খুব সময়সাপেক্ষ গবেষণায় জড়িত না করে প্রমাণ করতে পারি না। আপনি আমার কথাটি নিতে পারেন
চিয়ার্স এবং এইচটিএইচ - আলফ

1
@ স্টারগেটর "শেঠি (...) পর্যবেক্ষণ করেছেন যে নেদারল্যান্ডস অপারেটরগুলির অনেকগুলি সহজ হয়ে উঠবে যদি ইন্ডিয়ারেশন অপারেটরটিকে উপসর্গের পরিবর্তে পোস্টফিক্স অপারেটর হিসাবে নেওয়া হয় তবে ততক্ষণে এটি পরিবর্তন করতে খুব দেরী হয়েছিল।" ডিএমআর থেকে। অবশ্যই ডিএমআর কনস্ট এবং অস্থির কিওয়ার্ড আবিষ্কার করেনি, তারা সি ++ / এক্স 3 জ 11 থেকে এসেছে, যা এই পৃষ্ঠায় প্রমাণিত।
অ্যান্টি হাপাল

6

আমার জন্য, constযেমন অবস্থানটি বাম বা সঠিক থেকে প্রদর্শিত হয় বা ডানদিকে বা বামে এবং রাইট উভয়ের উপর নির্ভর *করে আমাকে আসল অর্থটি বের করতে সহায়তা করে।

  1. A constথেকে LEFT *ইঙ্গিত দেয় যে পয়েন্টার দ্বারা নির্দেশিত বস্তুটি একটি constবস্তু।

  2. A constথেকে RIGHT এর *নির্দেশ করে যে পয়েন্টারটি constপয়েন্টার।

নিম্নলিখিত টেবিলটি স্ট্যানফোর্ড CS106L স্ট্যান্ডার্ড সি ++ প্রোগ্রামিং ল্যাবরেটরি কোর্স রিডার থেকে নেওয়া হয়েছে।

এখানে চিত্র বর্ণনা লিখুন


3

এটি বেশিরভাগ ক্ষেত্রে দ্বিতীয় লাইনে সম্বোধন করে: সেরা অনুশীলন, অ্যাসাইনমেন্ট, ফাংশন প্যারামিটার ইত্যাদি

সাধারণ অভ্যাস. আপনি যা পারেন সব কিছু করার চেষ্টা করুন const। বা অন্য কোনও উপায়ে বলতে constগেলে, সবকিছু দিয়ে শুরু করার চেষ্টা করুন এবং তারপরে constপ্রোগ্রামটি কাজ করার অনুমতি দেওয়ার জন্য প্রয়োজনীয় ন্যূনতম সেটটি সরিয়ে দিন । কনস্ট্যান্ট-নির্ভুলতা অর্জনে এটি একটি বড় সহায়তা হবে এবং লোকেরা যখন এমন কিছু করার চেষ্টা করে যেগুলি তাদের সংশোধন করার কথা নয় তখন তাদের সূক্ষ্ম বাগগুলি প্রবর্তিত না হয় তা নিশ্চিত করতে সহায়তা করবে help

প্লেগের মতো কনস্ট_কাস্ট <> এড়িয়ে চলুন। এটির জন্য এক বা দুটি বৈধ ব্যবহারের কেস রয়েছে তবে সেগুলি খুব কম এবং এর মধ্যে খুব বেশি। যদি আপনি কোনও বিষয়বস্তু পরিবর্তন করার চেষ্টা করছেন const, আপনি যাকে constপ্রথম গতিতে ঘোষণা করেছেন তা খুঁজে বের করার জন্য এবং তার কী হবে তা নিয়ে conকমত্যে পৌঁছানোর জন্য তাদের সাথে বিষয়টি নিয়ে কথা বলার জন্য আপনি আরও অনেক বেশি কিছু করতে পারেন।

যা অ্যাসাইনমেন্টগুলিতে খুব ঝরঝরে করে নিয়ে যায়। আপনি যদি কোনও কিছু নির্ধারণ করতে পারেন তবে তা অবিচ্ছিন্ন। যদি আপনি কনস্টেন্ট এমন কোনও কিছুতে নির্ধারণ করতে চান তবে উপরে দেখুন। মনে রাখবেন যে ঘোষণাগুলিতে int const *foo;এবং int * const bar;বিভিন্ন জিনিসগুলি হ'ল const- এখানে অন্যান্য উত্তরগুলি সেই সমস্যাটি প্রশংসিতভাবে coveredেকে রেখেছে, তাই আমি তাতে প্রবেশ করব না।

ফাংশন পরামিতি:

মান দ্বারা পাস: উদাহরণস্বরূপ void func(int param)আপনি কলিং সাইটে এক উপায় বা অন্যদিকে যত্ন নেই। যুক্তিটি তৈরি করা যেতে পারে যে ফাংশনটি ডিক্লেয়ার করার জন্য ব্যবহারের কেস void func(int const param)রয়েছে তবে কেবলমাত্র ফাংশনটিতে কলারের উপর এর কোনও প্রভাব নেই, এতে যে মানটি পাস হয় তা কল করার সময় ফাংশন দ্বারা পরিবর্তন করা যায় না।

রেফারেন্স দ্বারা পাস: যেমন void func(int &param)এখন এটি একটি পার্থক্য করে। যেমন ঘোষিত funcহয়েছে পরিবর্তনের অনুমতি দেওয়া হয়েছেparam এবং যে কোনও কলিং সাইট পরিণতি মোকাবেলা করার জন্য প্রস্তুত থাকতে হবে। ঘোষণা void func(int const &param)পরিবর্তন করে চুক্তি পরিবর্তন করে, এবং গ্যারান্টি দেয় যা funcএখন পরিবর্তন করতে পারে না param, যার অর্থ যা পাস হয়েছিল তা হ'ল ফিরে আসবে। অন্যরা যেমন উল্লেখ করেছে যে আপনি যে কোনও বড় অব্জেক্ট পরিবর্তন করতে চান না তা সস্তাভাবে পাস করার জন্য এটি খুব কার্যকর। একটি বড় রেফারেন্সকে মান দ্বারা পাস করার চেয়ে রেফারেন্স পাস করা অনেক সস্তা।

পয়েন্টার দিয়ে পাস করুন: উদাহরণস্বরূপ void func(int *param)এবং void func(int const *param)এই দু'টি তাদের রেফারেন্স সমকক্ষগুলির সাথে অনেকটা সমার্থক, যাঁর নামক ফাংশনটি এখন nullptrঅন্য কোনও চুক্তিভিত্তিক গ্যারান্টি আশ্বাস না দিলে পরীক্ষা করা দরকার withfunc যে এটি একটি গ্রহণ করবে না nullptrparam

এই বিষয়ে মতামত টুকরা। এরকম ক্ষেত্রে যথার্থতা প্রমাণ করা নরকীয়ভাবে কঠিন, ভুল করা খুব সহজ। সুতরাং সম্ভাবনা নেবেন না এবং সর্বদা এর জন্য পয়েন্টার পরামিতিগুলি পরীক্ষা করুনnullptr । আপনি দীর্ঘমেয়াদে নিজেকে ব্যথা এবং যন্ত্রণা এবং ত্রুটিগুলি খুঁজে পাওয়া শক্ত করবেন will এবং চেকের ব্যয় হিসাবে, এটি ময়লা সস্তা, এবং যে ক্ষেত্রে সংকলকটিতে নির্মিত স্থির বিশ্লেষণ এটি পরিচালনা করতে পারে, অপটিমাইজার যেকোনভাবে এটি এডিট করবে। এমএসভিসির জন্য লিংক টাইম কোড জেনারেশন, বা জিসিসির জন্য ডাব্লুওপিআর (আমার মনে হয়) চালু করুন এবং আপনি এটি প্রশস্ত প্রোগ্রাম পাবেন, এমনকি এমন কোনও ফাংশন কলগুলিতে যা উত্স কোড মডিউল সীমানা অতিক্রম করে।

দিনের শেষে উপরের সমস্তগুলি সর্বদা পয়েন্টারগুলিতে রেফারেন্স পছন্দ করতে একটি খুব শক্ত কেস তৈরি করে। তারা কেবল চারদিকে নিরাপদ।


3

উভয় পক্ষের ইন্টের সাথে কনটটি ধ্রুবকটির জন্য পয়েন্টার তৈরি করবে :

const int *ptr=&i;

বা:

int const *ptr=&i;

constপরে ধীরে ধীরে পয়েন্টার* তৈরি করবে :

int *const ptr=&i;

এই ক্ষেত্রে এগুলি সমস্ত ধ্রুবক পূর্ণসংখ্যার দিকে নির্দেশক , তবে এগুলির কোনওটিই ধ্রুবক পয়েন্টার নয়:

 const int *ptr1=&i, *ptr2=&j;

এই ক্ষেত্রে সমস্ত ধ্রুবক পূর্ণসংখ্যার দিকে নির্দেশক এবং পিটিআর 2 হ'ল ধ্রুবক পূর্ণসংখ্যার প্রতি পয়েন্টার । তবে ptr1 ধ্রুবক পয়েন্টার নয়:

int const *ptr1=&i, *const ptr2=&j;

3
  • যদি constহয় বাঁদিকে এর *, এটা (মান বোঝায় এটা কোন ব্যাপার না কিনা এটা const intবাint const )
  • যদি constহয় ডানদিকে এর *, এটা পয়েন্টার নিজেই বোঝায়
  • এটি একই সাথে উভয় হতে পারে

একটি গুরুত্বপূর্ণ বিষয়: const int *p আপনি যে মানটিকে উল্লেখ করছেন তা ধ্রুবক নয়! । এর অর্থ হ'ল আপনি সেই পয়েন্টারের মাধ্যমে এটি পরিবর্তন করতে পারবেন না (অর্থাত্ আপনি $ * p = ... `নির্ধারণ করতে পারবেন না)। মান নিজেই অন্য উপায়ে পরিবর্তন করা যেতে পারে। যেমন

int x = 5;
const int *p = &x;
x = 6; //legal
printf("%d", *p) // prints 6
*p = 7; //error 

এটি বেশিরভাগ ফাংশন স্বাক্ষরগুলিতে ব্যবহার করার অর্থ, গ্যারান্টিটি দেওয়ার জন্য যে ফাংশনটি দুর্ঘটনাক্রমে পাস হওয়া যুক্তিগুলি পরিবর্তন করতে পারে না।


2

অন্যের ব্যাখ্যা অনুসরণ করে সি এর সম্পূর্ণতার স্বার্থে, সি ++ এর জন্য নিশ্চিত নন।

  • পিপি - পয়েন্টার থেকে পয়েন্টার
  • পি - পয়েন্টার
  • ডেটা - জিনিস উদাহরণস্বরূপ, নির্দেশিত x
  • গা bold় - কেবল পঠনযোগ্য পরিবর্তনশীল

ইশারা

  • পি তথ্য - int *p;
  • পি তথ্য -int const *p;
  • পি তথ্য -int * const p;
  • পি তথ্য -int const * const p;

পয়েন্টার পয়েন্টার

  1. পিপি পি ডেটা - int **pp;
  2. পিপি পি ডেটা -int ** const pp;
  3. পিপি পি ডেটা -int * const *pp;
  4. পিপি পি ডেটা -int const **pp;
  5. পিপি পি ডেটা -int * const * const pp;
  6. পিপি পি ডেটা -int const ** const pp;
  7. পিপি পি ডেটা -int const * const *pp;
  8. পিপি পি ডেটা -int const * const * const pp;
// Example 1
int x;
x = 10;
int *p = NULL;
p = &x;
int **pp = NULL;
pp = &p;
printf("%d\n", **pp);

// Example 2
int x;
x = 10;
int *p = NULL;
p = &x;
int ** const pp = &p; // Definition must happen during declaration
printf("%d\n", **pp);

// Example 3
int x;
x = 10;
int * const p = &x; // Definition must happen during declaration
int * const *pp = NULL;
pp = &p;
printf("%d\n", **pp);

// Example 4
int const x = 10; // Definition must happen during declaration
int const * p = NULL;
p = &x;
int const **pp = NULL;
pp = &p;
printf("%d\n", **pp);

// Example 5
int x;
x = 10;
int * const p = &x; // Definition must happen during declaration
int * const * const pp = &p; // Definition must happen during declaration
printf("%d\n", **pp);

// Example 6
int const x = 10; // Definition must happen during declaration
int const *p = NULL;
p = &x;
int const ** const pp = &p; // Definition must happen during declaration
printf("%d\n", **pp);

// Example 7
int const x = 10; // Definition must happen during declaration
int const * const p = &x; // Definition must happen during declaration
int const * const *pp = NULL;
pp = &p;
printf("%d\n", **pp);

// Example 8
int const x = 10; // Definition must happen during declaration
int const * const p = &x; // Definition must happen during declaration
int const * const * const pp = &p; // Definition must happen during declaration
printf("%d\n", **pp);

ডি-রেফারেন্সের এন-লেভেল

কেবল চালিয়ে যান, তবে মানবতা আপনাকে ছাড়িয়ে দেয়।

int x = 10;
int *p = &x;
int **pp = &p;
int ***ppp = &pp;
int ****pppp = &ppp;

printf("%d \n", ****pppp);

0
  1. const int*- ধ্রুবক intবস্তুর পয়েন্টার ।

আপনি পয়েন্টারের মান পরিবর্তন করতে পারেন; আপনি intবস্তুর মান পরিবর্তন করতে পারবেন না , পয়েন্টারটি নির্দেশ করে।


  1. const int * const- ধ্রুবক intবস্তুর কাছে ধ্রুবক পয়েন্টার ।

আপনি পয়েন্টারের মান বা পয়েন্টারকে নির্দেশিত intবস্তুর মান পরিবর্তন করতে পারবেন না ।


  1. int const *- ধ্রুবক intবস্তুর পয়েন্টার ।

এই বিবৃতিটি 1 এর সমান const int*- আপনি পয়েন্টারের মান পরিবর্তন করতে পারেন তবে আপনি intবস্তুর মান পরিবর্তন করতে পারবেন না , পয়েন্টারটি নির্দেশ করে।


আসলে, একটি চতুর্থ বিকল্প আছে:

  1. int * const- intআপত্তি স্থির পয়েন্টার ।

আপনি পয়েন্টারটি নির্দেশিত বস্তুর মান পরিবর্তন করতে পারেন তবে আপনি নিজে পয়েন্টারের মান পরিবর্তন করতে পারবেন না। পয়েন্টারটি সর্বদা একই intবস্তুর দিকে নির্দেশ করবে তবে এই বস্তুর এই মানটি intপরিবর্তন করা যেতে পারে।


আপনি যদি নির্দিষ্ট ধরণের সি বা সি ++ কনস্ট্রাক্ট নির্ধারণ করতে চান তবে আপনি ডেভিড অ্যান্ডারসনের তৈরি ক্লকওয়াইজ / সর্পিল বিধিটি ব্যবহার করতে পারেন ; তবে রস জে। অ্যান্ডারসনের তৈরি অ্যান্ডারসনের বিধি বিভ্রান্ত না করা , যা একেবারেই আলাদা।

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