এখানে একটি বিশদ ব্যাখ্যা যা আমি আশা করি সহায়ক হবে। আসুন আপনার প্রোগ্রামটি দিয়ে শুরু করুন, কারণ এটি ব্যাখ্যা করা সবচেয়ে সহজ।
int main()
{
const char *p = "Hello";
while(*p++)
printf("%c",*p);
return 0;
}
প্রথম বিবৃতি:
const char* p = "Hello";
p
একটি পয়েন্টার হিসাবে ঘোষণা char
। যখন আমরা "পয়েন্টার টু এ" বলি char
, তার অর্থ কী? এর অর্থ হল এর মান p
একটি এর ঠিকানা char
; p
স্মৃতিতে একটি রাখার জন্য কিছু স্থান রেখে দেওয়া হয়েছে তা আমাদের জানায় char
।
বিবৃতিটি p
আক্ষরিক স্ট্রিংয়ের প্রথম অক্ষরের দিকে ইঙ্গিত করার জন্যও সূচনা করে "Hello"
। এই অনুশীলনের খাতিরে, এটি p
পুরো স্ট্রিংকে নয়, কেবল প্রথম চরিত্রের দিকে নির্দেশ করে হিসাবে বোঝা গুরুত্বপূর্ণ 'H'
। সর্বোপরি, p
একটিতে একটি পয়েন্টার char
, পুরো স্ট্রিংয়ের জন্য নয়। এর মান p
এর ঠিকানা হল 'H'
মধ্যে "Hello"
।
তারপরে আপনি একটি লুপ সেট আপ করুন:
while (*p++)
লুপ শর্তটির *p++
অর্থ কী? তিনটি জিনিস এখানে কাজ করছে যা এই চমকপ্রদ করে তোলে (কমপক্ষে পরিচিতি স্থাপন না হওয়া পর্যন্ত):
- দুটি অপারেটরের অগ্রাধিকার, পোস্টফিক্স
++
এবং ইন্ডিরিয়েশন*
- পোস্টফিক্স ইনক্রিমেন্ট এক্সপ্রেশনের মান
- পোস্টফিক্স ইনক্রিমেন্ট এক্সপ্রেশন এর পার্শ্ব প্রতিক্রিয়া
1. অগ্রাধিকার । অপারেটরদের জন্য অগ্রাধিকার টেবিলের এক দ্রুত নজরে আপনাকে জানাতে হবে যে পোস্টফিক্স ইনক্রিমেন্টের অধিবেশন / ইন্ডিরিশন (15) এর চেয়ে উচ্চতর অগ্রাধিকার (16) রয়েছে। এর অর্থ এই যে জটিল অভিব্যক্তি *p++
যাচ্ছে যেমন দলবদ্ধ হবে: *(p++)
। অর্থাত্ *
অংশটি মানটির ক্ষেত্রে প্রয়োগ করা হবে p++
। সুতরাং p++
প্রথমে অংশ নেওয়া যাক ।
2. পোস্টফিক্স এক্সপ্রেশন মান । এর মান p++
হ'ল p
বর্ধনের পূর্বে মান । যদি তোমার থাকে:
int i = 7;
printf ("%d\n", i++);
printf ("%d\n", i);
আউটপুট হবে:
7
8
কারণ বর্ধিত হওয়ার আগে i++
মূল্যায়ন করে i
। একইভাবে p++
বর্তমান মান মূল্যায়ন করতে চলেছে p
। যেমনটি আমরা জানি, এর বর্তমান মান p
হল ঠিকানা 'H'
।
সুতরাং এখন p++
অংশটি *p++
মূল্যায়ন করা হয়েছে; এটির বর্তমান মান p
। তারপরে *
অংশটি ঘটে। *(current value of p)
অর্থ: দ্বারা রাখা ঠিকানায় মান অ্যাক্সেস করুন p
। আমরা জানি যে ঠিকানার মানটি 'H'
। সুতরাং এক্সপ্রেশন *p++
মূল্যায়ন 'H'
।
এখন বলুন এক মিনিট, আপনি বলছেন। যদি *p++
মূল্যায়ন করা হয় 'H'
, তবে কেন 'H'
উপরের কোডটিতে এটি মুদ্রণ হয় না ? পার্শ্ব প্রতিক্রিয়া আসে যেখানে সেখানে ।
৩. পোস্টফিক্স এক্সপ্রেশন এর পার্শ্ব প্রতিক্রিয়া । পোস্টসাফিক্স ++
হয়েছে মান বর্তমান প্রতীক, কিন্তু এটা আছে পার্শ্ব প্রতিক্রিয়া যে প্রতীক বৃদ্ধিশীল করুন। তাই না? int
আবার সেই কোডটি একবার দেখুন:
int i = 7;
printf ("%d\n", i++);
printf ("%d\n", i);
পূর্বে উল্লিখিত হিসাবে, আউটপুট হবে:
7
8
যখন i++
প্রথম মূল্যায়ন করা হয় printf()
, এটা 7. মূল্যায়ণ কিন্তু সি মান গ্যারান্টী যে কিছু সময়ে সামনে দ্বিতীয় printf()
নির্বাহ শুরু, পার্শ্ব প্রতিক্রিয়া এর ++
অপারেটর সঞ্চালিত হবে। অর্থাৎ দ্বিতীয়টি হওয়ার আগে printf()
, প্রথমটিতে অপারেটরের i
ফলস্বরূপ বৃদ্ধি করা হবে । এটি, যাইহোক, মানটি কয়েকটি গ্যারান্টিগুলির মধ্যে অন্যতম যা পার্শ্ব প্রতিক্রিয়াগুলির সময় সম্পর্কে জানায়।++
printf()
আপনার কোডে, তারপরে, যখন অভিব্যক্তিটি *p++
মূল্যায়ন করা হয়, তখন এটি মূল্যায়ন করে 'H'
। তবে আপনি এই সময় পাবেন:
printf ("%c", *p)
যে বিরক্তিকর পার্শ্ব প্রতিক্রিয়া ঘটেছে। p
বৃদ্ধি করা হয়েছে। ওহো! এটি আর নির্দেশ করে না 'H'
, তবে একটি চরিত্রের অতীতকে 'H'
: 'e'
অন্য কথায়। এটি আপনার ককনিফাইড আউটপুট ব্যাখ্যা করে:
ello
সুতরাং অন্যান্য উত্তরে সহায়ক (এবং নির্ভুল) পরামর্শের কোরাস: প্রাপ্ত উচ্চারণ মুদ্রণ করতে "Hello"
এবং এর ককনি অংশ নয়, আপনার মতো কিছু দরকার
while (*p)
printf ("%c", *p++);
এত কিছুর জন্য। বাকিদের কী হবে? আপনি এর অর্থ সম্পর্কে জিজ্ঞাসা করুন:
*ptr++
*++ptr
++*ptr
আমরা প্রায় প্রথম কথা বলত তাই SECOND এ লুক যাক: *++ptr
।
আমরা আমাদের পূর্বের ব্যাখ্যায় দেখেছি যে পোস্টফিক্স ইনক্রিমেন্টের p++
একটি নির্দিষ্ট নজির , একটি মান এবং একটি পার্শ্ব প্রতিক্রিয়া রয়েছে । প্রিফিক্স ইনক্রিমেন্টটি তার পোস্টফিক্স কাউন্টারটির মতো ++p
একই পার্শ্ব প্রতিক্রিয়াযুক্ত : এটি তার ক্রিয়াকলাপকে ১ দ্বারা বাড়িয়েছে However তবে এটির একটি পৃথক নজির এবং ভিন্ন মান রয়েছে ।
প্রিফিক্স ইনক্রিমেন্টের পোস্টফিক্সের চেয়ে কম অগ্রাধিকার রয়েছে; এটির প্রাধান্য 15 আছে other অন্য কথায়, এটি ডিগ্রিফারেন্স / ইন্ডিरेশন অপারেটরের মতো একই প্রাধান্য রয়েছে *
। মত একটি অভিব্যক্তি
*++ptr
কোন বিষয়টি প্রাধান্য নয়: দুটি অপারেটর অগ্রাধিকারের ক্ষেত্রে অভিন্ন। সুতরাং associativity কিক হবে। উপসর্গ বৃদ্ধি এবং অপ্রত্যক্ষ্যতার অপারেটর ডান-বাম associativity আছে। সেই সাহসীতার কারণে অপারেটরটি আরও বামে ptr
অপারেটরের ++
আগে ডানদিকের অপারেটরের সাথে গোষ্ঠীবদ্ধ হতে চলেছে *
। অন্য কথায়, অভিব্যক্তিটি গ্রুপবদ্ধ হতে চলেছে *(++ptr)
। সুতরাং, পাশাপাশি হিসাবে *ptr++
অন্য কারণের জন্য, এখানেও *
অংশটি মানটির জন্য প্রয়োগ করা হচ্ছে ++ptr
।
সুতরাং যে মান কি? প্রিফিক্স ইনক্রিমেন্ট এক্সপ্রেশনটির মান হ'ল ইনক্রিমেন্টের পরে অপারেন্ডের মান । এটি পোস্টফিক্স ইনক্রিমেন্ট অপারেটর থেকে একেবারে আলাদা জন্তুতে পরিণত করে। আসুন বলি আপনার কাছে রয়েছে:
int i = 7;
printf ("%d\n", ++i);
printf ("%d\n", i);
আউটপুটটি হবে:
8
8
... আমরা পোস্টফিক্স অপারেটরের সাথে যা দেখেছি তার থেকে আলাদা। একইভাবে, যদি আপনি:
const char* p = "Hello";
printf ("%c ", *p); // note space in format string
printf ("%c ", *++p); // value of ++p is p after the increment
printf ("%c ", *p++); // value of p++ is p before the increment
printf ("%c ", *p); // value of p has been incremented as a side effect of p++
আউটপুট হবে:
H e e l // good dog
দেখেন কেন?
আপনার সম্পর্কে আমরা জিজ্ঞাসা করা তৃতীয় অভিব্যক্তিটি এখন পেয়েছি ++*ptr
। আসলে এটিই অনেক জটিল। উভয় অপারেটরের একই প্রাধান্য এবং ডান-বাম সাহচর্য রয়েছে। এর অর্থ এক্সপ্রেশনটি গ্রুপ করা হবে ++(*ptr)
। ++
অংশ মান প্রয়োগ করা হবে *ptr
অংশ।
সুতরাং আমাদের যদি থাকে:
char q[] = "Hello";
char* p = q;
printf ("%c", ++*p);
আশ্চর্যজনকভাবে অহঙ্কারমূলক আউটপুট হতে চলেছে:
I
কি?! ঠিক আছে, সুতরাং *p
অংশটি মূল্যায়ন করতে চলেছে 'H'
। তারপরে ++
খেলাটি আসে, কোন সময়ে এটি প্রয়োগ করা হবে, বিন্দুটি 'H'
মোটেই নয়! আপনি 1 এ যুক্ত করলে কী হয় 'H'
? আপনি 1 এর সাথে 'H'
72 এর ASCII মান পান ; আপনি 73. উপস্থাপন করে একটি হিসাবে পেতে char
, এবং আপনি পেতে char
73 এর ASCII মান সঙ্গে 'I'
।
এটি আপনার প্রশ্নে আপনি যে তিনটি অভিব্যক্তি সম্পর্কে জিজ্ঞাসা করেছিলেন সেটির যত্ন নেয়। আপনার প্রশ্নের প্রথম মন্তব্যে উল্লিখিত আরেকটি এখানে রয়েছে:
(*ptr)++
এটি একটি আকর্ষণীয়। যদি তোমার থাকে:
char q[] = "Hello";
char* p = q;
printf ("%c", (*p)++);
printf ("%c\n", *p);
এটি আপনাকে এই উত্সাহী আউটপুট দেবে:
HI
কি হচ্ছে? আবার এটি প্রাধান্য , অভিব্যক্তি মান এবং পার্শ্ব প্রতিক্রিয়াগুলির বিষয় । বন্ধনীগুলির কারণে, *p
অংশটি প্রাথমিক অভিব্যক্তি হিসাবে বিবেচিত হয়। প্রাথমিক এক্সপ্রেশন অন্য সব কিছু ট্রাম্প; তারা প্রথমে মূল্যায়ন করা। এবং *p
, আপনি জানেন হিসাবে, মূল্যায়ন 'H'
। বাকী বাক্য ++
অংশটি সেই মানটিতে প্রয়োগ করা হয়। সুতরাং, এই ক্ষেত্রে, (*p)++
হয়ে যায় 'H'++
।
এর মান কী 'H'++
? আপনি যদি বলেন 'I'
, আপনি পোস্টফিক্স ইনক্রিমেন্টের সাথে মান বনাম পার্শ্ব প্রতিক্রিয়া সম্পর্কে আমাদের আলোচনাটি ইতিমধ্যে ভুলে গেছেন (ইতিমধ্যে!) মনে রাখবেন, 'H'++
এর বর্তমান মানটির মূল্যায়ন করে 'H'
। সুতরাং যে প্রথম printf()
মুদ্রণ যাচ্ছে 'H'
। তারপরে, পার্শ্ব প্রতিক্রিয়া হিসাবে , এতে 'H'
বাড়ানো হচ্ছে 'I'
। দ্বিতীয় printf()
প্রিন্ট যে 'I'
। এবং আপনি আপনার প্রফুল্ল শুভেচ্ছা আছে।
ঠিক আছে, তবে শেষ দুটি ক্ষেত্রে আমার কেন দরকার আছে
char q[] = "Hello";
char* p = q;
কেন আমি ঠিক যেমন কিছু করতে পারি না
/*const*/ char* p = "Hello";
printf ("%c", ++*p); // attempting to change string literal!
কারণ "Hello"
একটি স্ট্রিং আক্ষরিক। যদি আপনি চেষ্টা করেন তবে আপনি স্ট্রিংটিতে পুরো স্ট্রিংটি তৈরি করে ++*p
পাল্টানোর চেষ্টা করছেন । সি তে, স্ট্রিং লিটারেলগুলি কেবল পঠনযোগ্য; তাদের সংশোধন করার চেষ্টা অনির্ধারিত আচরণের জন্য প্রার্থনা করে। ইংরেজিতেও অপরিজ্ঞাত, তবে এটি কেবল কাকতালীয়।'H'
'I'
"Iello"
"Iello"
বিপরীতে, আপনি থাকতে পারে না
char p[] = "Hello";
printf ("%c", *++p); // attempting to modify value of array identifier!
কেন না? কারণ এই উদাহরণে, p
একটি অ্যারে হয়। একটি অ্যারে কোনও পরিবর্তনযোগ্য এল-মান নয়; আপনি p
পূর্ব বা পোস্ট-ইনক্রিমেন্ট বা হ্রাস দ্বারা পয়েন্টগুলি পরিবর্তন করতে পারবেন না কারণ অ্যারের নামটি স্থির পয়েন্টার হিসাবে কাজ করে। (এটি আসলে যা তা নয়; এটি দেখার পক্ষে এটি কেবল একটি সুবিধাজনক উপায়))
মোট কথা, আপনি যে তিনটি বিষয় সম্পর্কে জিজ্ঞাসা করেছেন তা এখানে:
*ptr++ // effectively dereferences the pointer, then increments the pointer
*++ptr // effectively increments the pointer, then dereferences the pointer
++*ptr // effectively dereferences the pointer, then increments dereferenced value
এবং এখানে চতুর্থটি, অন্য তিনটির মতো প্রতিটি মজার পরিমাণ:
(*ptr)++ // effectively forces a dereference, then increments dereferenced value
প্রথম এবং দ্বিতীয়টি ক্র্যাশ হবে যদি ptr
আসলে কোনও অ্যারে সনাক্তকারী হয়। তৃতীয় এবং চতুর্থ ক্র্যাশ হয়ে যাবে যদি ptr
একটি স্ট্রিং আক্ষরিককে নির্দেশ করে।
ওখানে তোমার আছে। আমি আশা করি এখন সব ক্রিস্টাল। আপনি দুর্দান্ত শ্রোতা হয়েছিলেন, এবং আমি সারা সপ্তাহ এখানে থাকব।
(*ptr)++
(বন্ধনীগুলি থেকে পৃথক করা দরকার*ptr++
)