আপনার প্রশ্নটি সম্ভবত ছিল না, "কেন সিগুলিতে এইগুলি নির্ধারিত আচরণ করা হয়?"। আপনার প্রশ্ন সম্ভবত ছিল, "কেন এই কোডটি (ব্যবহার করে ++
) আমাকে প্রত্যাশিত মূল্য দেয় নি?", এবং কেউ আপনার প্রশ্নটিকে সদৃশ হিসাবে চিহ্নিত করেছে এবং আপনাকে এখানে পাঠিয়েছে।
এই উত্তরটি সেই প্রশ্নের উত্তর দেওয়ার চেষ্টা করে: আপনার কোডটি আপনার প্রত্যাশিত উত্তরটি কেন দেয় নি এবং আপনি কীভাবে প্রত্যাশা অনুযায়ী কাজ করবে না এমন অভিব্যক্তিগুলি সনাক্ত করতে (এবং এড়ানো) শিখতে পারেন।
আমি ধরে নিয়েছি আপনি এখনই সি ++
এবং --
অপারেটরগুলির প্রাথমিক সংজ্ঞা শুনেছেন এবং উপসর্গ ফর্মটি কীভাবে ++x
পোস্টফিক্স ফর্মের থেকে পৃথক রয়েছে x++
। তবে এই অপারেটরগুলি সম্পর্কে চিন্তা করা শক্ত, তাই আপনি বুঝতে পেরেছেন তা নিশ্চিত করার জন্য, সম্ভবত আপনি একটি ছোট্ট একটি ছোট্ট পরীক্ষা প্রোগ্রাম লিখেছিলেন যাতে এর মতো কিছু রয়েছে invol
int x = 5;
printf("%d %d %d\n", x, ++x, x++);
কিন্তু, আপনার আশ্চর্যের বিষয়, এই প্রোগ্রামটি হয়নি না সাহায্য আপনি বুঝতে - এটা কিছু অদ্ভুত, অপ্রত্যাশিত, অবক্তব্য আউটপুট মুদ্রিত, বোঝা যায় যে হয়তো ++
সম্পূর্ণ ভিন্ন কিছু, না এ সব আপনি চিন্তা কি তা আছে।
অথবা, আপনি সম্ভবত একটি হার্ড-টু বোঝার মত প্রকাশের দিকে তাকিয়ে আছেন
int x = 5;
x = x++ + ++x;
printf("%d\n", x);
ধাঁধা হিসাবে কেউ আপনাকে এই কোডটি দিয়েছে। এই কোডটিও কোনও তাত্পর্যপূর্ণ নয়, বিশেষত আপনি যদি এটি চালান - এবং আপনি যদি এটি দুটি পৃথক সংকলকের অধীনে সংকলন এবং চালনা করেন তবে আপনি সম্ভবত দুটি পৃথক উত্তর পেতে পারেন! কি হয়েছে? কোন উত্তরটি সঠিক? (এবং উত্তরটি হ'ল উভয়ই, না উভয়ই রয়েছে))
আপনি এখনই শুনেছেন, এই সমস্ত এক্সপ্রেশনগুলি অপরিজ্ঞাত , যার অর্থ সি ভাষা তারা কী করবে সে সম্পর্কে কোনও গ্যারান্টি দেয় না। এটি একটি আশ্চর্যজনক এবং আশ্চর্যজনক ফলাফল, কারণ আপনি সম্ভবত ভেবেছিলেন যে কোনও প্রোগ্রাম আপনি লিখতে পারবেন, যতক্ষণ এটি সংকলিত এবং চালিত হবে, একটি অনন্য, সু-সংজ্ঞায়িত আউটপুট তৈরি করবে। তবে অপরিজ্ঞাত আচরণের ক্ষেত্রে তা হয় না।
কী একটি অভিব্যক্তি অপরিজ্ঞাত করে তোলে? অভিব্যক্তিগুলি জড়িত ++
এবং --
সর্বদা অপরিবর্তিত? অবশ্যই নয়: এগুলি দরকারী অপারেটর এবং আপনি যদি এগুলি সঠিকভাবে ব্যবহার করেন তবে সেগুলি পুরোপুরি সুসংজ্ঞায়িত।
আমরা একবারে যখন খুব বেশি কিছু ঘটতে চলেছে তখন তাদের কী অপরিজ্ঞাপিত করে তোলে সে সম্পর্কে আমরা যে অভিব্যক্তিগুলির সাথে কথা বলছি তা হ'ল কখন কী অর্ডার হবে তা আমরা নিশ্চিত নই, তবে যখন অর্ডারটি আমাদের ফলাফলের দিকে আসে।
এই উত্তরে আমি যে দুটি উদাহরণ ব্যবহার করেছি সেগুলিতে ফিরে আসি। আমি যখন লিখেছি
printf("%d %d %d\n", x, ++x, x++);
প্রশ্নটি হল, কল করার আগে printf
, সংকলকটি x
প্রথমটির মান গণনা করে , বা x++
, বা হতে পারে ++x
? কিন্তু দেখা যাচ্ছে যে আমরা জানি না । সি-তে কোনও নিয়ম নেই যা বলে যে কোনও ক্রিয়াকলাপের যুক্তিগুলি বাম থেকে ডানে, বা ডান থেকে বামে বা অন্য কোনও ক্রমে মূল্যায়ন করা হয়। সুতরাং আমরা বলতে পারি না যে সংকলকটি x
প্রথমে, তারপরে ++x
, তারপরে x++
বা x++
তারপরে কি করবে++x
তারপর x
, অথবা অন্য অর্ডার। তবে অর্ডারটি স্পষ্টভাবে গুরুত্বপূর্ণ, কারণ সংকলকটি কোন আদেশটি ব্যবহার করে তার উপর নির্ভর করে আমরা স্পষ্টভাবে মুদ্রিত বিভিন্ন ফলাফল পাব printf
।
এই পাগল প্রকাশ সম্পর্কে কি?
x = x++ + ++x;
এই অভিব্যক্তিটির সমস্যাটি হ'ল এতে x এর মানটি সংশোধন করার জন্য তিনটি পৃথক প্রচেষ্টা রয়েছে: (1) x++
অংশটি 1 টি x এ যুক্ত করার চেষ্টা করে, নতুন মানটি সংরক্ষণ করে x
এবং এর পুরানো মানটি ফিরিয়ে আনার চেষ্টা করে x
; (২) ++x
অংশটি 1 থেকে x যোগ করার চেষ্টা করে, নতুন মানটি সংরক্ষণ করে x
এবং এর নতুন মানটি ফিরিয়ে আনার চেষ্টা করে x
; এবং (3)x =
অংশটি অন্য দু'জনের যোগফলকে x এ নির্ধারণ করার চেষ্টা করে। এই তিনটি চেষ্টা করা অ্যাসাইনমেন্টের মধ্যে কোনটি "জিতবে"? তিনটি মানগুলির মধ্যে কোনটি আসলে অর্পণ করা হবে x
? আবার, এবং সম্ভবত আশ্চর্যজনকভাবে, সিতে আমাদের বলার কোনও নিয়ম নেই।
আপনি কল্পনা করতে পারেন যে অগ্রাধিকার বা সাহচর্য বা বাম থেকে ডান মূল্যায়ন আপনাকে কী আদেশ ক্রম ঘটে তা বলে দেয় তবে তারা তা করে না। আপনি আমাকে বিশ্বাস করতে পারেন না, তবে দয়া করে এটির জন্য আমার শব্দটি গ্রহণ করুন, এবং আমি এটি আবার বলব: অগ্রাধিকার এবং সাহচর্যতা সিতে কোনও অভিব্যক্তির মূল্যায়নের আদেশের প্রতিটি দিক নির্ধারণ করে না বিশেষত, যদি একটি অভিব্যক্তির মধ্যে একাধিক থাকে বিভিন্ন স্পট যেখানে আমরা যেমন কোনও কিছুকে নতুন মান নির্ধারণ করার চেষ্টা করি x
, প্রাধান্য এবং সাহচর্যতা আমাদের জানায় না যে এই প্রচেষ্টাগুলির মধ্যে কোনটি প্রথমে হয় বা শেষ হয়, বা যে কোনও কিছুর হয়।
সুতরাং যে সমস্ত ব্যাকগ্রাউন্ড এবং উপস্থাপনের বাইরে, আপনি যদি নিশ্চিত করতে চান যে আপনার সমস্ত প্রোগ্রামগুলি যথাযথভাবে সংজ্ঞায়িত হয়েছে, আপনি কোন অভিব্যক্তি লিখতে পারেন এবং কোনটি আপনি লিখতে পারবেন না?
এই এক্সপ্রেশন সব ঠিক আছে:
y = x++;
z = x++ + y++;
x = x + 1;
x = a[i++];
x = a[i++] + b[j++];
x[i++] = a[j++] + b[k++];
x = *p++;
x = *p++ + *q++;
এই অভিব্যক্তিগুলি সমস্ত অপরিশোধিত:
x = x++;
x = x++ + ++x;
y = x + x++;
a[i] = i++;
a[i++] = i;
printf("%d %d %d\n", x, ++x, x++);
এবং শেষ প্রশ্নটি হ'ল আপনি কীভাবে বলতে পারবেন কোনটি এক্সপ্রেশন ভালভাবে সংজ্ঞায়িত হয়েছে এবং কোনটি এক্সপ্রেশনটি অপরিজ্ঞাত?
যেমনটি আমি আগেই বলেছি, অপরিজ্ঞাত প্রকাশগুলি হ'ল যেখানে খুব বেশি একবারে ঘটছে, যেখানে আপনি নিশ্চিত হতে পারবেন না কোন জিনিসগুলি কী ঘটবে এবং যেখানে আদেশের বিষয়টি গুরুত্বপূর্ণ:
- যদি এমন একটি পরিবর্তনশীল থাকে যা দুটি বা আরও বেশি জায়গায় সংশোধিত হয়ে থাকে (নির্ধারিত হয়) তবে আপনি কীভাবে জানবেন যে কোন পরিবর্তনটি প্রথমে ঘটে?
- যদি কোনও ভেরিয়েবল থাকে যা এক জায়গায় পরিবর্তিত হচ্ছে এবং এর মান অন্য জায়গায় ব্যবহার করা হচ্ছে তবে আপনি কীভাবে জানবেন যে এটি পুরানো মান ব্যবহার করে বা নতুন মানটি ব্যবহার করে?
অভিব্যক্তিতে # 1 এর উদাহরণ হিসাবে
x = x++ + ++x;
এক্স পরিবর্তন করতে তিনটি প্রচেষ্টা আছে।
অভিব্যক্তিতে # 2 এর উদাহরণ হিসাবে
y = x + x++;
আমরা উভয় এর মান ব্যবহার x
এবং এটি সংশোধন করি।
সুতরাং এটির উত্তর: আপনি যে কোনও এক্সপ্রেশন লিখেছেন তা নিশ্চিত করুন, প্রতিটি ভেরিয়েবল একবারে সংশোধন করা হয়েছে, এবং যদি কোনও ভেরিয়েবল সংশোধন করা হয়, আপনি সেই পরিবর্তনশীলটির মান অন্য কোথাও ব্যবহার করার চেষ্টা করবেন না।