I = i ++ + 1 কী করেছে; সি +++ এ আইনী?


186

আপনি নির্ধারিত আচরণের চিৎকার শুরু করার আগে এটি N4659 (সি ++ 17)সুস্পষ্টভাবে তালিকাভুক্ত করা হয়েছে

  i = i++ + 1;        // the value of i is incremented

তবুও N3337 এ (সি ++ 11)

  i = i++ + 1;        // the behavior is undefined

কী বদলে গেল?

আমি যা সংগ্রহ করতে পারি সেগুলি থেকে, [N4659 basic.exec]

উল্লিখিত ব্যতীত, পৃথক অপারেটরগুলির ক্রিয়াকলাপগুলির মূল্যায়ন এবং স্বতন্ত্র এক্সপ্রেশনগুলির subexpresstions অসমর্থিত। [...] অপারেটরের অপারেন্ডসের মান গণনা অপারেটরের ফলাফলের মান গণনার আগে ক্রমযুক্ত হয়। একই মেমোরি অবস্থানের অন্য কোনও পার্শ্ব প্রতিক্রিয়া বা একই মেমরির অবস্থানের কোনও বস্তুর মান ব্যবহার করে একটি মূল্য গণনার তুলনায় যদি কোনও মেমরির অবস্থানের পার্শ্ব প্রতিক্রিয়াটি অসম্পূর্ণ হয় এবং সেগুলি সম্ভাব্য একযোগে না হয়, তবে আচরণটি সংজ্ঞায়িত।

যেখানে মানটি [N4659 বেসিক.টাইপ] এ সংজ্ঞায়িত করা হয়েছে

তুচ্ছভাবে অনুলিপিযোগ্য প্রকারের জন্য, মান উপস্থাপনা হ'ল অবজেক্টের উপস্থাপনায় বিটের একটি সেট যা একটি মান নির্ধারণ করে , যা প্রয়োগের সংজ্ঞায়িত মানগুলির একটি পৃথক উপাদান

থেকে [N3337 basic.exec]

উল্লিখিত ব্যতীত, পৃথক অপারেটরগুলির ক্রিয়াকলাপগুলির মূল্যায়ন এবং স্বতন্ত্র এক্সপ্রেশনগুলির সুব্যাক্রেশনগুলি অসমর্থিত। [...] অপারেটরের অপারেন্ডসের মান গণনা অপারেটরের ফলাফলের মান গণনার আগে ক্রমযুক্ত হয়। যদি কোনও স্কেলার অবজেক্টের পার্শ্ব প্রতিক্রিয়া একই স্কেলার অবজেক্টের অন্য কোনও পার্শ্ব প্রতিক্রিয়া বা একই স্কেলার অবজেক্টের মান ব্যবহার করে একটি মান গণনার তুলনায় অসম্পূর্ণ হয়, তবে আচরণটি অপরিজ্ঞাত।

তেমনিভাবে, মানটিকে [N3337 বেসিক.টাইপ] এ সংজ্ঞায়িত করা হয়

তুচ্ছভাবে অনুলিপিযোগ্য প্রকারের জন্য, মান উপস্থাপনা হ'ল অবজেক্টের উপস্থাপনায় বিটের একটি সেট যা একটি মান নির্ধারণ করে , যা একটি প্রয়োগ-সংজ্ঞায়িত মানগুলির একটি পৃথক উপাদান।

এগুলি সমানত্বের উল্লেখ ব্যতীত অভিন্ন, যা বিবেচ্য নয় এবং স্কেলার অবজেক্টের পরিবর্তে মেমরির অবস্থান ব্যবহারের সাথে , যেখানে

পাটিগণিত প্রকার, গণনার প্রকার, পয়েন্টার প্রকার, সদস্য প্রকারের নির্দেশক std::nullptr_t, এবং এই ধরণের সিভি-যোগ্য সংস্করণগুলিকে সম্মিলিতভাবে স্কেলার প্রকার বলা হয়।

যা উদাহরণকে প্রভাবিত করে না।

থেকে [N4659 expr.ass]

অ্যাসাইনমেন্ট অপারেটর (=) এবং যৌগিক নিয়োগ অপারেটরগুলি সমস্ত গ্রুপকে ডান থেকে বামে। সবার জন্য তাদের বাম অপারেন্ড হিসাবে একটি পরিবর্তনযোগ্য লভ্যালু প্রয়োজন এবং বাম অপারেন্ডকে উল্লেখ করে একটি লভালিউটি ফিরিয়ে দিন। বাম অপারেন্ডটি যদি কিছুটা বিট-ফিল্ড হয় তবে সমস্ত ক্ষেত্রে ফলাফলটি একটি বিট-ফিল্ড is সমস্ত ক্ষেত্রে, অ্যাসাইনমেন্টটি ডান এবং বাম অপারেন্ডগুলির মান গণনা এবং অ্যাসাইনমেন্ট এক্সপ্রেশনটির মান গণনার আগে ক্রমযুক্ত হয়। বাম অপারেন্ডের আগে ডান অপরেন্ডটি সিকোয়েন্সড হয়।

থেকে [N3337 expr.ass]

অ্যাসাইনমেন্ট অপারেটর (=) এবং যৌগিক নিয়োগ অপারেটরগুলি সমস্ত গ্রুপকে ডান থেকে বামে। সবার জন্য তাদের বাম অপারেন্ড হিসাবে একটি পরিবর্তনযোগ্য লভ্যালু প্রয়োজন এবং বাম অপারেন্ডকে উল্লেখ করে একটি লভালিউটি ফিরিয়ে দিন। বাম অপারেন্ডটি যদি কিছুটা বিট-ফিল্ড হয় তবে সমস্ত ক্ষেত্রে ফলাফলটি একটি বিট-ফিল্ড is সমস্ত ক্ষেত্রে, অ্যাসাইনমেন্টটি ডান এবং বাম অপারেন্ডগুলির মান গণনার পরে এবং অ্যাসাইনমেন্ট এক্সপ্রেশনটির মান গণনার আগে ক্রমযুক্ত হয়।

কেবলমাত্র পার্থক্যটি সর্বশেষ বাক্যটি N3337 এ অনুপস্থিত ab

যেমন বাম প্রতীক শেষ বাক্য অবশ্য কোনো গুরুত্ব না iতন্ন তন্ন হয় "অন্য পার্শ্ব প্রতিক্রিয়া" কিংবা "একই স্কালে বস্তুর মান ব্যবহার" হিসাবে আইডি প্রকাশ একটি lvalue হয়।


23
আপনি কারণটি শনাক্ত করেছেন: সি ++ 17-এ, বাম অপারেন্ডের আগে ডান অপরেন্ডটি সিকোয়েন্সড হয়। সি ++ 11 তে এরকম কোনও অনুক্রম ছিল না। ঠিক কী, আপনার প্রশ্নটি কি?
রব

4
@ রবᵩ শেষ বাক্যটি দেখুন।
পাসার 19

7
এই পরিবর্তনের অনুপ্রেরণার সাথে কি কারও লিঙ্ক রয়েছে? কোড পছন্দ করার সময় আমি একটি স্থিতিশীল বিশ্লেষককে "আপনি এটি করতে চান না" বলতে সক্ষম হতে চান i = i++ + 1;

7
@ নীলবুটারওয়ার্থ, এটি পেজ p0145r3.pdf থেকে রয়েছে : " আইডোমেটিক সি ++ এর জন্য এক্সপ্রেশন মূল্যায়ন আদেশ সংশোধন করা হচ্ছে"।
xaizek

9
2 নীলবাটারওয়ার্থ, বিভাগ 2 নম্বর বলছেন যে এটি স্বজ্ঞাত পাল্টা এবং এমনকি বিশেষজ্ঞরা সব ক্ষেত্রেই সঠিক কাজ করতে ব্যর্থ হন। এটাই তাদের সমস্ত প্রেরণা pretty
xaizek

উত্তর:


144

সি ++ ১১-এ "অ্যাসাইনমেন্ট" এর অ্যাক্ট, অর্থাৎ এলএইচএস সংশোধন করার পার্শ্ব-প্রতিক্রিয়াটি ডান অপারেন্ডের মান গণনার পরে ক্রমযুক্ত হয় । মনে রাখবেন যে এটি তুলনামূলকভাবে "দুর্বল" গ্যারান্টি: এটি কেবল আরএইচএসের মান গণনার সাথে সম্পর্কিত ক্রম উত্পাদন করে । এটি আরএইচএসে উপস্থিত হতে পারে এমন পার্শ্ব-প্রতিক্রিয়াগুলি সম্পর্কে কিছুই বলে না , যেহেতু পার্শ্ব-প্রতিক্রিয়া সংঘটিত হওয়া মান গণনার অংশ নয় । সি ++ 11 এর প্রয়োজনীয়তা অ্যাসাইনমেন্টের কাজ এবং আরএইচএসের কোনও পার্শ্ব প্রতিক্রিয়াগুলির মধ্যে কোনও আপেক্ষিক ক্রম প্রতিষ্ঠা করে না। এটিই ইউবির সম্ভাবনা তৈরি করে।

এই ক্ষেত্রে একমাত্র আশা হ'ল আরএইচএসে ব্যবহৃত নির্দিষ্ট অপারেটরদের দ্বারা করা অতিরিক্ত গ্যারান্টি। আরএইচএস যদি একটি উপসর্গ ব্যবহার করে, এর উপসর্গের সাথে সম্পর্কিত ++বৈশিষ্ট্যগুলি সিকোয়েন্সিংয়ের ++উদাহরণটি উদাহরণটিতে এই দিনটি সংরক্ষণ করতে পারত। তবে পোস্টফিক্স ++একটি আলাদা গল্প: এটি এরকম গ্যারান্টি দেয় না। সি ++ 11 এর পার্শ্ব প্রতিক্রিয়াগুলি =এবং পোস্টফিক্সের ++এই উদাহরণটিতে একে অপরের সাথে সম্পর্কহীনতার অবসান ঘটে। এবং এটি ইউবি।

সি ++ 17 এ এসাইনমেন্ট অপারেটরের স্পেসিফিকেশনে একটি অতিরিক্ত বাক্য যুক্ত করা হয়েছে:

বাম অপারেন্ডের আগে ডান অপরেন্ডটি সিকোয়েন্সড হয়।

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

(@ জন বলিঙ্গারের মন্তব্যগুলি আমলে নিতে আপডেট হয়েছে Updated)


3
"বাম হাত অপারেণ্ড" দ্বারা আবৃত প্রভাবগুলিতে "অংশের আসল কাজ" অন্তর্ভুক্ত করা কি সত্যিই সঠিক? প্রকৃত নিয়োগের ক্রম সম্পর্কে স্ট্যান্ডার্ডের আলাদা ভাষা রয়েছে। আপনি যে অংশটি উপস্থাপন করেছেন তা বাম-হাত এবং ডান হাতের সাব-এক্সপ্রেশনগুলির সিকোয়েন্সিংয়ের সীমাবদ্ধতার জন্য সীমাবদ্ধ রেখেছি, যা এই বিভাগের বাকী অংশগুলির সাথে একত্রে যথেষ্ট বলে মনে হয় না, - ওপির বক্তব্যটির সংজ্ঞা।
জন বলিঞ্জার

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

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

1
@ কাজ: যৌগিক কার্যভারের জন্য, ডান পাশের পরে বাম পাশের মান মূল্যায়ন সম্পাদন x -= y;করা mov eax,[y] / sub [x],eaxতার চেয়ে ভাল কিছু প্রক্রিয়া করার সুযোগ দেয় mov eax,[x] / neg eax / add eax,[y] / mov [x],eax। আমি সে সম্পর্কে অডিওডিক কিছু দেখছি না। যদি কোনওটিকে একটি অর্ডার নির্দিষ্ট করতে হয়, সর্বাধিক দক্ষ অর্ডারিংয়ে সম্ভবত প্রথমে বাম দিকের অবজেক্টটি সনাক্ত করার জন্য প্রয়োজনীয় সমস্ত গণনা সম্পাদন করা হবে , তারপরে ডান অপারেণ্ডটি, তারপরে বাম বস্তুর মানটি মূল্যায়ন করুন, তবে এর জন্য একটি শব্দ থাকা দরকার বাম বস্তুর আইডিটি সমাধান করার ক্রিয়াটির জন্য।
সুপারক্যাট

1
@Kaz: যদি xএবং yছিল volatile, যে পার্শ্ব প্রতিক্রিয়া হবে। তদুপরি, একই বিবেচনাগুলি প্রযোজ্য x += f();, যেখানে f()পরিবর্তিত হয় x
সুপারক্যাট

33

আপনি নতুন বাক্যটি চিহ্নিত করেছেন

বাম অপারেন্ডের আগে ডান অপরেন্ডটি সিকোয়েন্সড হয়।

এবং আপনি সঠিকভাবে সনাক্ত করেছেন যে লভ্যালু হিসাবে বাম অপারেন্ডের মূল্যায়ন অপ্রাসঙ্গিক। যাইহোক, পূর্বে সিকোয়েন্সড একটি ট্রানজিটিভ সম্পর্ক হিসাবে নির্দিষ্ট করা হয়। সম্পূর্ণ অধিকার প্রতীক (পোস্ট-বৃদ্ধি সহ) তাই হয় এছাড়াও নিয়োগ সামনে সিকোয়েন্স। সি ++ ১১-এ, অ্যাসাইনমেন্টের আগে কেবল ডান অপরেন্ডের মান গণনা অনুক্রমিকভাবে করা হয়েছিল।


7

পুরানো সি ++ স্ট্যান্ডার্ড এবং সি 11 এ, অ্যাসাইনমেন্ট অপারেটর পাঠ্যের সংজ্ঞা পাঠ্যের সাথে শেষ হয়:

অপারেশনগুলির মূল্যায়ন অপরিশোধিত।

মানে অপারেন্ডগুলিতে পার্শ্ব-প্রতিক্রিয়াগুলি অমীমাংসিত এবং তাই যদি তারা একই পরিবর্তনশীল ব্যবহার করে তবে অবশ্যই সংজ্ঞায়িত আচরণ und

এই পাঠ্যটি কিছুটা অস্পষ্ট রেখে কেবল সি ++ 11 এ সরানো হয়েছিল। এটি ইউবি নাকি তা নয়? এটি C ++ 17 এ স্পষ্ট করা হয়েছে যেখানে তারা যুক্ত করেছে:

বাম অপারেন্ডের আগে ডান অপরেন্ডটি সিকোয়েন্সড হয়।


পার্শ্ব নোট হিসাবে, এমনকি পুরানো মানকগুলিতেও, এগুলি সমস্ত পরিষ্কার করা হয়েছিল, উদাহরণস্বরূপ C99 থেকে:

অপারেশনগুলির মূল্যায়নের ক্রমটি অনির্ধারিত। যদি কোনও অ্যাসাইনমেন্ট অপারেটরের ফলাফলটি সংশোধন করার জন্য বা পরবর্তী সিকোয়েন্স পয়েন্টের পরে এটি অ্যাক্সেস করার চেষ্টা করা হয়, তবে আচরণটি সংজ্ঞায়িত।

মূলত, C11 / C ++ 11 এ, তারা এই পাঠ্যটি সরিয়ে ফেললে তারা বিশৃঙ্খলা করল।


1

এটি অন্যান্য উত্তরের আরও তথ্য এবং নীচের কোডটি প্রায়শই পাশাপাশি জিজ্ঞাসা করা হওয়ায় এটি পোস্ট করছি

অন্যান্য উত্তরের ব্যাখ্যাটি সঠিক এবং নীচের কোডেও প্রযোজ্য যা এখন ভালভাবে সংজ্ঞায়িত হয়েছে (এবং এর সঞ্চিত মান পরিবর্তন করে না i):

i = i++;

+ 1একটি লাল হেরিং এবং এটি সত্যিই পরিষ্কার না কেন স্ট্যান্ডার্ড তাদের উদাহরণ মধ্যে এটি ব্যবহৃত যদিও আমি সি ++ 11 হয়তো পূর্বে মেইলিং লিস্ট তর্ক রিকল মানুষ না + 1আলাদা কিছু করি কারণে ডান ভোরে lvalue রূপান্তর অত্যাচার থেকে হাত পাশ অবশ্যই এর কোনওটিই C ++ 17 তে প্রযোজ্য নয় (এবং সম্ভবত সি ++ এর কোনও সংস্করণে কখনও প্রয়োগ হয়নি)।

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