চ (i = -1, i = -1) অপরিজ্ঞাত আচরণ কেন?


267

আমি মূল্যায়নের লঙ্ঘনের ক্রম সম্পর্কে পড়ছিলাম এবং তারা একটি উদাহরণ দেয় যা আমাকে ধাঁধা দেয়।

1) যদি স্কেলার অবজেক্টের কোনও পার্শ্ব প্রতিক্রিয়া একই স্কেলার অবজেক্টের অন্য পার্শ্ব প্রতিক্রিয়ার তুলনায় আন-সিকোয়েন্সড হয় তবে আচরণটি অপরিজ্ঞাত।

// snip
f(i = -1, i = -1); // undefined behavior

এই প্রসঙ্গে, iএকটি স্কেলার অবজেক্ট , যা আপাতভাবে বোঝায়

পাটিগণিত প্রকার (9.৯.১), গণনার প্রকার, পয়েন্টার প্রকার, পয়েন্টার টু মেম্বার টাইপ (9.৯.২), স্টাড :: নাল্পটার_টি, এবং এই ধরণের সিভি-কোয়ালিটিড ভার্সন (৩.৯.৩) সম্মিলিতভাবে স্কেলার প্রকার বলে।

সেক্ষেত্রে বিবৃতিটি কীভাবে অস্পষ্ট তা আমি দেখতে পাই না। আমার কাছে মনে হয় প্রথম বা দ্বিতীয় যুক্তির মূল্যায়ন যদি প্রথমে iকরা হয় তবে তার সমাপ্তি ঘটে -1এবং উভয় যুক্তিও একই রকম -1

কেউ দয়া করে স্পষ্ট করতে পারেন?


হালনাগাদ

আমি সত্যিই সমস্ত আলোচনার প্রশংসা করি। এখনও অবধি, আমি @ ক্ষতিকারকদের উত্তরটি অনেক পছন্দ করি যেহেতু এটি প্রথম নজরে কতটা সোজা এগিয়ে দেখায় তবুও এই বিবৃতিটি সংজ্ঞায়িত করার সমস্যাগুলি এবং জটিলতাগুলি প্রকাশ করে। @ অচিয়ং ৮87 কিছু উল্লেখ রয়েছে যা রেফারেন্সগুলি ব্যবহার করার সময় উঠে আসে তবে আমি মনে করি যে এটি এই প্রশ্নের অনিশ্চিত পার্শ্ব প্রতিক্রিয়াগুলির দিক থেকে অরথগোনাল।


সারসংক্ষেপ

এই প্রশ্নটি যেহেতু এক টন মনোযোগ পেয়েছে, তাই আমি মূল পয়েন্টগুলি / উত্তরগুলির সংক্ষিপ্তসার করব। প্রথমে, আমাকে একটি ছোট ডিগ্রেশন চিহ্নিত করতে অনুমতি দিন যে "কেন" খুব সূক্ষ্মভাবে পৃথক অর্থের সাথে সম্পর্কিত হতে পারে, যথা "কী কারণে ", "কোন কারণে " এবং "কী উদ্দেশ্যে "। তারা যে কারণে "কেন" বোঝায় সেগুলির মধ্যে কোনটির দ্বারা আমি উত্তরগুলিকে গ্রুপ করব।

কি কারণে

এখানে মূল উত্তরটি পল ড্রাগার থেকে এসেছে , মার্টিন জে যেমন একটি একইরকম অবদান রেখেছিলেন তবে ব্যাপক উত্তর হিসাবে নয়। পল ড্রাগার এর উত্তর ফোটে

এটি অপরিজ্ঞাত আচরণ কারণ এটি আচরণটি কী তা সংজ্ঞায়িত করা হয় না।

উত্তরটি সি ++ স্ট্যান্ডার্ড কী বলে তা বোঝানোর ক্ষেত্রে সামগ্রিকভাবে খুব ভাল। এটি ইউবির সম্পর্কিত কিছু ক্ষেত্রে যেমন f(++i, ++i);এবং তেমন সমাধান করে f(i=1, i=-1);। সম্পর্কিত ক্ষেত্রে প্রথমটিতে, এটি প্রথম স্পষ্ট নয় যে প্রথম যুক্তিটি হওয়া উচিত i+1এবং দ্বিতীয়টি i+2বা তদ্বিপরীত; দ্বিতীয়টিতে, এটি স্পষ্ট নয় যে iফাংশন কলের পরে 1 বা -1 হওয়া উচিত। এই দুটি ক্ষেত্রেই ইউবি হওয়ায় তারা নিম্নলিখিত নিয়মের আওতায় পড়ে:

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

সুতরাং, f(i=-1, i=-1)একই সাথে ইউবিও যেহেতু এটি একই নিয়মের আওতায় আসে, তবুও প্রোগ্রামারের উদ্দেশ্য (আইএমএইচও) সুস্পষ্ট এবং দ্ব্যর্থহীন।

পল ড্রাগারও তার উপসংহারে এটি স্পষ্ট করে তুলেছেন

এটি আচরণ সংজ্ঞায়িত করা যেতে পারে? হ্যাঁ. এটি সংজ্ঞায়িত ছিল? না।

যা আমাদের "এই কারণে কেন / উদ্দেশ্যকে f(i=-1, i=-1)অপরিজ্ঞাত আচরণ হিসাবে রেখে গেছে?" এমন প্রশ্নে নিয়ে আসে ?

কি কারণে / উদ্দেশ্যে

যদিও সি ++ স্ট্যান্ডার্ডে কিছু তদারকি (সম্ভবত অসাবধান) রয়েছে, তবে অনেকগুলি বাদ দেওয়া যথাযথ যুক্তিযুক্ত এবং একটি নির্দিষ্ট উদ্দেশ্যে পরিবেশন করে। যদিও আমি সচেতন যে উদ্দেশ্যটি প্রায়শই হয় "সংকলক-লেখকের কাজকে সহজ করে তোলে", বা "দ্রুত কোড", তবে ইউবি হিসাবে কোনও ভাল কারণ ছাড়ার কারণ আছে কিনা তা জানতে আমি আগ্রহী ছিলাম f(i=-1, i=-1)

harmic এবং supercat প্রধান উত্তর করে একটি প্রদান প্রদান কারণ UB জন্য। হার্মিক উল্লেখ করে যে একটি অপ্টিমাইজ করা সংকলক যা সম্ভবত একাধিক মেশিনের নির্দেশাবলীতে পরমাণু নির্ধারিত ক্রিয়াকলাপ ভেঙে ফেলতে পারে এবং এটি সর্বোত্তম গতির জন্য সেই নির্দেশাবলীটি আরও ফাঁকা রাখতে পারে। এটি কিছু চমকপ্রদ ফলাফলের দিকে নিয়ে যেতে পারে: iতার দৃশ্যে -2 হিসাবে শেষ হয়! সুতরাং, ক্ষতিকারক প্রদর্শন করে যে চলকটিতে একই মানটিকে একবারের চেয়ে আরও একবারে নির্ধারণ করা যদি অপারেশনগুলি অনিরাপদ করা হয় তবে কীভাবে খারাপ প্রভাব ফেলতে পারে।

সুপারক্যাট f(i=-1, i=-1)যা করা উচিত তা দেখে মনে হচ্ছে যা করার চেষ্টা করার ক্ষতির একটি সম্পর্কিত চিত্র প্রদর্শন করে । তিনি উল্লেখ করেছেন যে কিছু স্থাপত্যে একই মেমরি ঠিকানায় একসাথে একাধিক লেখার বিরুদ্ধে কঠোর বিধিনিষেধ রয়েছে। যদি আমরা এর চেয়ে কম তুচ্ছ কিছু নিয়ে কাজ করি তবে একটি সংকলককে এটি ধরতে বেশ কঠিন সময় থাকতে পারে f(i=-1, i=-1)

davidf খুব harmic এর অনুরূপ interleaving নির্দেশাবলীর একটি উদাহরণ প্রদান করে।

যদিও প্রত্যেকটি ক্ষতিকারক, সুপারক্যাট এবং ডেভিডফের উদাহরণগুলি কিছুটা সংশ্লেষিত, একত্রিত হয়ে তারা এখনও একটি f(i=-1, i=-1)সংজ্ঞায়িত কারণ প্রদানের জন্য পরিবেশন করে যে কেন অপরিজ্ঞাত আচরণ করা উচিত।

আমি হারিকের জবাব গ্রহণ করেছি কারণ কেন পল ড্রেপারের উত্তর "কী কারণে" অংশটিকে আরও ভালভাবে সম্বোধন করেছিল, তার সমস্ত অর্থকে সম্বোধন করার সেরা কাজটি করেছিল।

অন্যান্য উত্তর

জনবি উল্লেখ করেছে যে আমরা যদি ওভারলোডেড অ্যাসাইনমেন্ট অপারেটরগুলি (কেবল প্লেইন স্কেলারের পরিবর্তে) বিবেচনা করি তবে আমরাও সমস্যার মধ্যে পড়তে পারি।


1
একটি স্কেলার অবজেক্ট হল স্কেলারের ধরণের একটি অবজেক্ট। ৩.৯ / ৯ দেখুন: "গাণিতিক প্রকার (9.৯.১), গণনার ধরন, পয়েন্টার প্রকার, পয়েন্টার টু মেম্বার টাইপ (৩.৯.২) std::nullptr_tএবং সিভি- কোয়ালিটিড সংস্করণ (৩.৯.৩) সম্মিলিতভাবে স্কেলার প্রকার বলে । "
রব কেনেডি

1
পৃষ্ঠায় সম্ভবত একটি ত্রুটি রয়েছে এবং এগুলি আসলে বোঝায় f(i-1, i = -1)বা অনুরূপ কিছু।
মিস্টার লিস্টার

এই প্রশ্নটি একবার দেখুন: stackoverflow.com/a/4177063/71074
রবার্ট এস বার্নেস

ধন্যবাদ রব কেনেডি "গাণিতিক ধরণের "গুলিতে কি বুল অন্তর্ভুক্ত?
নিকু স্টুর্কা

1
আপনার আপডেটটি উত্তর বিভাগে হওয়া উচিত igh
গ্রিজেশ চৌহান

উত্তর:


343

যেহেতু অপারেশনগুলি অনিবার্য, তাই বলার অপেক্ষা রাখে না যে কার্য সম্পাদনের নির্দেশাবলী আন্তঃলিপি করা যায় না। সিপিইউ আর্কিটেকচারের উপর নির্ভর করে এটি করা সর্বোত্তম হতে পারে। রেফারেন্সযুক্ত পৃষ্ঠাটি এতে বলেছে:

যদি A এর পূর্বে B এবং B এর পূর্বে অনুক্রম না হয় তবে দুটি সম্ভাবনা বিদ্যমান:

  • এ এবং বি এর মূল্যায়নগুলি অনিচ্ছাকৃত: এগুলি কোনও ক্রমে সম্পাদন করা হতে পারে এবং ওভারল্যাপ হতে পারে (মৃত্যুদন্ডের একক থ্রেডের মধ্যে, সংকলক সি এবং সি-র নির্দেশনাগুলিকে বিভক্ত করতে পারে যা এ এবং বি সমন্বিত থাকে)

  • A এবং B এর মূল্যায়নগুলি অনির্দিষ্টভাবে ক্রমযুক্ত: এগুলি কোনও ক্রমে সম্পাদন করা যেতে পারে তবে ওভারল্যাপ নাও হতে পারে: হয় A এর পূর্বে সম্পূর্ণ হবে, বা B এ এর ​​পূর্বে সম্পূর্ণ হবে আদেশটি পরের বার একই অভিব্যক্তির বিপরীত হতে পারে মূল্যায়ন করা হয়।

এটি নিজে থেকেই মনে হয় না যে এটি কোনও সমস্যার কারণ হতে পারে - ধরে নিই যে ক্রিয়াকলাপটি করা হচ্ছে মান -1 একটি মেমরির জায়গায় সংরক্ষণ করছে। তবে এটিও বলার অপেক্ষা রাখে না যে সংকলক একই নির্দেশাবলীর পৃথক পৃথক সেটগুলিতে এটি অনুকূলিত করতে পারে না তবে একই মেমরির স্থানে অপারেশনটির সাথে অপারেশনটি ইন্টারলিভ করা থাকলে এটি ব্যর্থ হতে পারে।

উদাহরণস্বরূপ, কল্পনা করুন যে এটি মেমরির শূন্য করতে আরও দক্ষ ছিল, তারপরে এটি হ্রাস করুন, মান -1 ইন-লোড করার সাথে তুলনা করুন this

f(i=-1, i=-1)

হতে পারে:

clear i
clear i
decr i
decr i

এখন আমি -2।

এটি সম্ভবত একটি বোগাস উদাহরণ, তবে এটি সম্ভব।


59
সিকোয়েন্সিং বিধি মেনে চলার সময় কীভাবে অভিব্যক্তিটি আসলে অপ্রত্যাশিত কিছু করতে পারে তার খুব সুন্দর উদাহরণ। হ্যাঁ, কিছুটা ভাগ্যবান, তবে কোডটি স্নিপড করে আমি প্রথমে জিজ্ঞাসা করছি। :)
নিকু স্টুর্কা

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

11
উভয় প্যারামিটারে একই ভেরিয়েবলের জন্য একই মান নির্ধারণের ফলে কীভাবে অপ্রত্যাশিত ফলাফল আসতে পারে তার উদাহরণটি আমি সত্যিই পছন্দ করি কারণ দুটি অ্যাসাইনমেন্ট অপরিবর্তিত
মার্টিন জে

1
যে বিন্দুটির জন্য সংকলিত কোডটি আপনি আশা করেন তা সর্বদা +1e + 6 (ঠিক আছে, +1) নয়। আপনি যখন বিধিগুলি অনুসরণ করেন না তখন এই ধরণের বক্ররেখা আপনার দিকে ছুঁড়ে ফেলার ক্ষেত্রে অপ্টিমাইজারগুলি সত্যিই ভাল: পি
কোরি

3
আর্ম প্রসেসরে একটি লোড 32 বিট 4 টি নির্দেশ নিতে পারে: এটি load 8bit immediate and shift4 বার পর্যন্ত করে। সাধারণত সংকলক এটিকে এড়ানোর জন্য একটি সংখ্যা আনার জন্য অপ্রত্যক্ষ ঠিকানা করবে table (-1 1 নির্দেশে করা যেতে পারে তবে অন্য একটি উদাহরণ বেছে নেওয়া যেতে পারে)।
ctrl-alt-delor

208

প্রথমত, "স্কালে বস্তুর" একটি মত একটি টাইপ মানে int, float, অথবা একটি পয়েন্টার (দেখুন কি C ++ স্কেলের সর্বস্ব কোনও জীব? )।


দ্বিতীয়ত, এটি আরও সুস্পষ্ট বলে মনে হতে পারে

f(++i, ++i);

অপরিবর্তিত আচরণ হবে। কিন্তু

f(i = -1, i = -1);

কম স্পষ্ট হয়।

কিছুটা আলাদা উদাহরণ:

int i;
f(i = 1, i = -1);
std::cout << i << "\n";

"শেষ" কোন কার্যভারটি ঘটেছে i = 1, বা i = -1? এটি স্ট্যান্ডার্ডে সংজ্ঞায়িত হয়নি। সত্যিই, মানে iহতে পারে 5(এই কিভাবে ক্ষেত্রে হতে chould জন্য একটি সম্পূর্ণ বিশ্বাসযোগ্য ব্যাখ্যা জন্য এর harmic উত্তর দেখুন)। অথবা আপনি প্রোগ্রাম segfault পারে। অথবা আপনার হার্ড ড্রাইভটির পুনরায় ফর্ম্যাট করুন।

তবে এখন আপনি জিজ্ঞাসা করছেন: "আমার উদাহরণটি সম্পর্কে কী? আমি -1উভয় কার্যভারের জন্য একই মান ( ) ব্যবহার করেছি that এ সম্পর্কে সম্ভবত অস্পষ্ট হতে পারে কি?"

আপনি সঠিক ... সি ++ মান কমিটি যেভাবে বর্ণনা করেছে তা ব্যতীত।

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

তারা আপনার বিশেষ কেসের জন্য একটি বিশেষ ব্যতিক্রম করতে পারত , কিন্তু তারা তা করেনি। (এবং তাদের কেন করা উচিত? সম্ভবত এটির কী ব্যবহার হবে?) সুতরাং, iএখনও হতে পারে 5। অথবা আপনার হার্ড ড্রাইভ খালি থাকতে পারে। সুতরাং আপনার প্রশ্নের উত্তরটি হ'ল:

এটি অপরিজ্ঞাত আচরণ কারণ এটি আচরণটি কী তা সংজ্ঞায়িত করা হয় না।

(এটি জোরের দাবিদার কারণ অনেক প্রোগ্রামার মনে করেন "অপরিজ্ঞাত" মানে "এলোমেলো", বা "অপ্রত্যাশিত" It এটি নয়; এর অর্থ মান দ্বারা সংজ্ঞায়িত নয় The আচরণটি 100% ধারাবাহিক হতে পারে এবং এখনও অপরিবর্তিত হতে পারে))

এটি আচরণ সংজ্ঞায়িত করা যেতে পারে? হ্যাঁ. এটি সংজ্ঞায়িত ছিল? না। সুতরাং এটি "অপরিজ্ঞাত"।

এটি বলেছিল, "অপরিবর্তিত" এর অর্থ এই নয় যে কোনও সংকলক আপনার হার্ড ড্রাইভকে ফর্ম্যাট করবে ... এর অর্থ এটি এটি হতে পারে এবং এটি এখনও একটি মান-অনুসারী সংকলক হতে পারে। বাস্তবতাত্ত্বিকভাবে, আমি নিশ্চিত g ++, ঝনঝন এবং এমএসভিসি সকলেই আপনার প্রত্যাশা অনুযায়ী কাজ করবে। তারা শুধু "করতে" হবে না।


একটি ভিন্ন প্রশ্ন হতে পারে যে কেন সি ++ স্ট্যান্ডার্ড কমিটি এই পার্শ্ব-প্রতিক্রিয়াটিকে অনিচ্ছাকৃত করতে বেছে নিয়েছিল? । এই উত্তরটি ইতিহাসের এবং কমিটির মতামতকে জড়িত করবে। অথবা এই পার্শ্ব-প্রতিক্রিয়াটি সি ++ এ অসম্পৃক্ত থাকা সম্পর্কে ভাল কি? , যা কোনও ন্যায়সঙ্গতের অনুমতি দেয়, এটি কিনা স্ট্যান্ডার্ড কমিটির আসল যুক্তি ছিল কি না। আপনি এই প্রশ্নগুলি এখানে, বা প্রোগ্রামার.সটাকেক্সচেঞ্জ.কম এ জিজ্ঞাসা করতে পারেন।


9
@ এইচডিডি, হ্যাঁ, আসলে আমি জানি যে আপনি -Wsequence-pointজি ++ এর জন্য সক্ষম করলে তা আপনাকে সতর্ক করবে।
পল

47
"আমি নিশ্চিত জি ++, কলং এবং এমএসভিসি সকলেই আপনার প্রত্যাশা অনুযায়ী কাজ করবে" আমি একটি আধুনিক সংকলককে বিশ্বাস করব না। তারা খারাপ। উদাহরণস্বরূপ তারা বুঝতে পারে যে এটি অনির্ধারিত আচরণ এবং এই কোডটি অ্যাক্সেসযোগ্য নয় ass তারা যদি আজ তা না করে তবে তারা আগামীকাল তা করতে পারে। যে কোনও ইউবি হ'ল টিকিং টাইম বোমা।
কোডসইনচাউস

8
@ ব্ল্যাকলাইটশাইনিং "আপনার উত্তরটি খারাপ না কারণ এটি খারাপ নয়" খুব কার্যকর প্রতিক্রিয়া নয়, তাই না?
ভিনসেন্ট ভ্যান ডের ওয়েইল

13
@ BobJarvis সংকলনগুলির অপরিজ্ঞাত আচরণের সময় এমনকি দূরবর্তী অবস্থান থেকে সঠিক কোড উত্পন্ন করার কোনও বাধ্যবাধকতা নেই। টিআইটি এমনকি ধরে নিতে পারে যে এই কোডটি কখনও কল করা হয় না এবং এইভাবে পুরো জিনিসটি একটি ন্যাপ দিয়ে প্রতিস্থাপন করে (নোট করুন যে কম্পাইলাররা প্রকৃতপক্ষে ইউবির মুখের মধ্যে এমন অনুমান করে)) অতএব আমি বলব যে এই ধরনের বাগের প্রতিবেদনের সঠিক প্রতিক্রিয়া কেবল "বন্ধ,
গ্রিজলি

7
@ শিগশ্যাচাগ কখনও কখনও শর্তাদির পুনর্বিবেচনা (যা কেবলমাত্র পৃষ্ঠের উপর একটি টোটোলজিকাল জবাব বলে মনে হয়) মানুষের প্রয়োজন। প্রযুক্তিগত বৈশিষ্ট্যে নতুন বেশিরভাগ লোকেরা এর undefined behaviorঅর্থ ভাবেন something random will happen, যা বেশিরভাগ সময় ক্ষেত্রে থেকে দূরে থাকে।
ইজকাটা

27

নিয়ম থেকে ব্যতিক্রম না করার একটি ব্যবহারিক কারণ কেবলমাত্র দুটি মান একই:

// config.h
#define VALUEA  1

// defaults.h
#define VALUEB  1

// prog.cpp
f(i = VALUEA, i = VALUEB);

কেসটি অনুমোদিত হয়েছিল তা বিবেচনা করুন।

এখন, কয়েক মাস পরে, পরিবর্তনের প্রয়োজন দেখা দেয়

 #define VALUEB 2

আপাতদৃষ্টিতে নিরীহ, তাই না? এবং তবু হঠাৎ প্রগসিপিপি আর সংকলন করবে না। তবুও, আমরা মনে করি যে সংকলনটি একটি আক্ষরিকের মানের উপর নির্ভর করে না।

নীচের লাইন: নিয়মের ব্যতিক্রম নেই কারণ এটি সফল সংকলনটি একটি ধ্রুবকের মান (বরং প্রকারের) উপর নির্ভর করে।

সম্পাদনা

@ হার্টওয়্যার উল্লেখ করেছেন যে ফর্মটির ধ্রুবক প্রকাশগুলি A DIV Bকিছু ভাষায়, যখন B0 হয় তখন অনুমোদিত হয় না এবং সংকলন ব্যর্থ হওয়ার কারণ হয়। সুতরাং ধ্রুবক পরিবর্তন অন্য কোনও স্থানে সংকলনের ত্রুটি ঘটাতে পারে। যা হ'ল আইএমএইচও, দুর্ভাগ্যজনক। তবে এই জাতীয় জিনিসগুলি অনিবার্যভাবে সীমাবদ্ধ করা অবশ্যই ভাল।


অবশ্যই, তবে উদাহরণটি পূর্ণসংখ্যার আক্ষরিক ব্যবহার করে । আপনার f(i = VALUEA, i = VALUEB);অবশ্যই অপরিজ্ঞাত আচরণের সম্ভাবনা রয়েছে। আমি আশা করি আপনি শনাক্তকারীদের পিছনে মূল্যবোধের সাথে কোডিং করছেন না।
ওল্ফ

3
@ ওয়াল্ড তবে সংকলক প্রিপ্রোসেসর ম্যাক্রোগুলি দেখতে পাবে না। এমনকি যদি এটি নাও হয় তবে কোনও প্রোগ্রামিং ভাষার ক্ষেত্রে উদাহরণ খুঁজে পাওয়া শক্ত, যেখানে উত্স কোডটি 1 থেকে 2 অবধি কিছুটা ধ্রুবক পরিবর্তন না হওয়া অবধি সংকলিত হয় এটি কেবল অগ্রহণযোগ্য এবং অব্যক্ত নয়, আপনি এখানে খুব ভাল ব্যাখ্যা দেখতে পাচ্ছেন see কেন সেই কোডটি একই মান সহ ভেঙে যায়।
ইনগো

হ্যাঁ, সংকলনগুলি ম্যাক্রোগুলি দেখতে পায় না। কিন্তু, এই প্রশ্ন ছিল?
নেকড়ে

1
আপনার উত্তরটি বিন্দুটি অনুপস্থিত, হারিকের উত্তর এবং এটিতে ওপির মন্তব্য পড়ুন।
উলফ

1
এটা করতে পারে SomeProcedure(A, B, B DIV (2-A))। যাইহোক, যদি ভাষাটি বলে যে সংকলনের সময় কনস্টের অবশ্যই পুরো মূল্যায়ন করা উচিত, তবে অবশ্যই, আমার দাবিটি সে ক্ষেত্রে কার্যকর নয়। যেহেতু এটি কোনওভাবেই সংকলন এবং রানটাইমের পার্থক্যটিকে ঝাপসা করে। আমরা যদি লিখি তাও কি খেয়াল করবে CONST C = X(2-A); FUNCTION X:INTEGER(CONST Y:INTEGER) = B/Y; ?? বা ফাংশন অনুমোদিত না?
ইনগো

12

বিভ্রান্তিটি হ'ল স্থানীয় ভেরিয়েবলের মধ্যে ধ্রুবক মান সংরক্ষণ করা প্রতিটি আর্কিটেকচারে সি চালানোর জন্য ডিজাইন করা একটি পরমাণু নির্দেশ নয়। প্রসেসর কোডটি এই ক্ষেত্রে সংকলকটির চেয়ে বেশি বিষয়ে চালিত হয়। উদাহরণস্বরূপ, এআরএমে যেখানে প্রতিটি নির্দেশ সম্পূর্ণ 32 বিট ধ্রুবক বহন করতে পারে না, ভেরিয়েবলের মধ্যে কোন int সংরক্ষণ করে সেই নির্দেশের আরও বেশি প্রয়োজন। এই সিউডো কোডের উদাহরণ যেখানে আপনি একবারে কেবল 8 টি বিট সংরক্ষণ করতে পারবেন এবং 32 বিট রেজিস্টারে কাজ করতে হবে, আমি একটি অন্তর্গত 32:

reg = 0xFF; // first instruction
reg |= 0xFF00; // second
reg |= 0xFF0000; // third
reg |= 0xFF000000; // fourth
i = reg; // last

আপনি কল্পনা করতে পারেন যে সংকলকটি এটি অনুকূল করতে চাইলে এটি একই ক্রমটি দু'বার অন্তরঙ্গ করতে পারে এবং আপনি কী জানেন যে আমি কী মান লিখব; এবং বলা যাক তিনি খুব স্মার্ট নন:

reg = 0xFF;
reg |= 0xFF00;
reg |= 0xFF0000;
reg = 0xFF;
reg |= 0xFF000000;
i = reg; // writes 0xFF0000FF == -16776961
reg |= 0xFF00;
reg |= 0xFF0000;
reg |= 0xFF000000;
i = reg; // writes 0xFFFFFFFF == -1

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


আমি মনে করি যে এআরএম-এ সংকলকটি কেবল একটি টেবিল থেকে ধ্রুবকটি লোড করবে। আপনি যা বর্ণনা করেছেন তা এমআইপিএসের মতো মনে হয়।
এইচ

1
@ অ্যান্ড্রে চের্নিখোভস্কি ইয়েপ, তবে কোনও ক্ষেত্রে যখন এটি সহজভাবে হয় না -1(যে সংকলকটি কোথাও সংরক্ষণ করেছে), তবে এটি বরং 3^81 mod 2^32, তবে ধ্রুবক, তখন সংকলকটি এখানে যা ঘটেছে ঠিক তা করতে পারে, এবং কিছুটা বাদ দেওয়ার পরে, আমার আন্তঃলিপি কল কল অনুসরণ করেছে অপেক্ষা এড়াতে।
yo

@ টেকেস, হ্যাঁ, আমি এটি ইতিমধ্যে পরীক্ষা করে দেখেছি। আসলে, সংকলকটি একটি টেবিল থেকে প্রতিটি ধ্রুবক লোড করার জন্য খুব স্মার্ট। যাইহোক, এটি দুটি ধ্রুবক গণনা করতে একই রেজিস্টার কখনও ব্যবহার করবে না। এটি নিশ্চিতভাবে নির্ধারিত আচরণকে 'অপরিবর্তিত' করবে।
এইচ

@ আন্ড্রেচেরেনিখভস্কি তবে আপনি সম্ভবত "বিশ্বের প্রতিটি সি ++ কম্পাইলার প্রোগ্রামার" নন। মনে রাখবেন যে কেবল 3 গণনার জন্য 3 টি শর্ট রেজিস্টার সহ এমন মেশিন রয়েছে।
ইয়ো '

@ টেকেকস, দুটি পৃথক বস্তু f(i = A, j = B)কোথায় iএবং jতা উদাহরণ বিবেচনা করুন । এই উদাহরণটির কোনও ইউবি নেই। মেশিন 3 সংক্ষিপ্ত রেজিস্টার থাকার কম্পাইলার দুই মান মিশে জন্য কোন অজুহাত নেই Aএবং Bকারণ এটি প্রোগ্রামের শব্দার্থবিদ্যা বিরতি দেবে, একই রেজিস্টারে (যেমন @ davidf এর উত্তরে দেখানো হয়েছে)।
এইচ

11

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

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

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

uint8_t v;  // Global

void hey(uint8_t *p)
{
  moo(v=5, (*p)=6);
  zoo(v);
  zoo(v);
}

সংকলক যদি "moo" এ কল করে এবং এটি "v" সংশোধন করে না তা বলতে পারে, এটি একটি 5 থেকে v সংরক্ষণ করতে পারে, তারপরে একটি 6 থেকে * পি সঞ্চয় করতে পারে, তারপরে 5 "চিড়িয়াখানা" থেকে পাস করবে এবং তারপরে ভি এর সামগ্রীগুলি "চিড়িয়াখানা" তে পাস করুন। যদি "চিড়িয়াখানা" "v" সংশোধন না করে তবে দুটি কলকে আলাদা আলাদা মান দেওয়ার কোনও উপায় নেই, তবে এটি যে কোনওভাবেই ঘটতে পারে। অন্যদিকে, উভয় স্টোর একই মান লিখবে এমন ক্ষেত্রে, এই ধরণের অদ্ভুততা দেখা দিতে পারে না এবং বেশিরভাগ প্ল্যাটফর্মে অদ্ভুত কিছু করার বাস্তবায়নের কোনও বুদ্ধিমান কারণ থাকতে পারে না। দুর্ভাগ্যক্রমে, কিছু সংকলক লেখককে "স্ট্যান্ডার্ড এটি অনুমতি দেয়" এর বাইরে নির্বাক আচরণের জন্য কোনও অজুহাত লাগবে না, সুতরাং এমনকি সেই মামলাগুলিও নিরাপদ নয়।


9

সত্য যে ফলাফলে সবচেয়ে বাস্তবায়নের একই হবে এই ক্ষেত্রে আনুষঙ্গিক হয়; মূল্যায়নের ক্রম এখনও অপরিজ্ঞাত। বিবেচনা করুন f(i = -1, i = -2): এখানে, বিষয়গুলি অর্ডার করুন। আপনার উদাহরণে এটির গুরুত্বের একমাত্র কারণটি হ'ল দুর্ঘটনা হ'ল উভয় মান -1

অপ্রকাশিত আচরণের সাথে অভিব্যক্তিটি একটি হিসাবে নির্দিষ্ট করা হয়েছে, এটি কার্যকরভাবে নির্ধারণ করা সংকলক একটি f(i = -1, i = -1)কার্যকর চিত্রটি প্রদর্শন করতে পারে যখন আপনি নির্বাহের মূল্যায়ন ও বাতিল করেন - এবং এখনও পুরোপুরি সঠিক হিসাবে বিবেচিত হবে। ভাগ্যক্রমে, কোনও সংকলকও আমি এটি সম্পর্কে সচেতন নই।


8

এটি আমার কাছে ফাংশন আর্গুমেন্ট এক্সপ্রেশনটির সিকোয়েন্সিং সম্পর্কিত একমাত্র নিয়মের মতো এখানে দেখাচ্ছে:

3) কোনও ফাংশন কল করার সময় (ফাংশনটি ইনলাইন রয়েছে কিনা এবং এবং সুস্পষ্ট ফাংশন কল সিনট্যাক্স ব্যবহৃত হয়েছে কিনা তা), যখন কোনও যুক্তি প্রকাশের সাথে যুক্ত প্রতিটি মান গণনা এবং পার্শ্ব প্রতিক্রিয়া, বা ডাকটি ফাংশনকে মনোনীত পোস্টফিক্স এক্সপ্রেশন সহ, হয় ডাকা ফাংশনটির শরীরে প্রতিটি অভিব্যক্তি বা বিবৃতি কার্যকর করার আগে ক্রমযুক্ত।

এটি আর্গুমেন্ট এক্সপ্রেশনগুলির মধ্যে ক্রম সংজ্ঞা দেয় না, সুতরাং আমরা এই ক্ষেত্রে শেষ করি:

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

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

void f(int l, int r) {
    return l < -1;
}
auto b = f(i = -1, i = -2);
if (b) {
    formatDisk();
}

8

সি ++ 17 কঠোর মূল্যায়নের বিধিগুলি সংজ্ঞায়িত করে। বিশেষত, এটি ফাংশন আর্গুমেন্টগুলি সিকোয়েন্স করে (যদিও অনির্দিষ্ট ক্রমে)।

N5659 §4.6:15
মূল্যায়ন একটি এবং বি অনিশ্চিতভাবে সিকোয়েন্স যখন পারেন একটি সামনে সিকোয়েন্স করা হয় বি বা বি সামনে সিকোয়েন্স করা হয় একটি , কিন্তু এটা যা অনির্দিষ্ট হয়। [ দ্রষ্টব্য : নির্বিচারে ক্রমযুক্ত মূল্যায়নগুলি ওভারল্যাপ করতে পারে না, তবে হয় প্রথমে কার্যকর করা যেতে পারে। - শেষ নোট ]

N5659 § 8.2.2:5
প্রতিটি সম্পর্কিত মান গণনা এবং পার্শ্ব প্রতিক্রিয়া সহ একটি প্যারামিটারের সূচনাটি অনির্দিষ্টকালের জন্য অন্য যে কোনও প্যারামিটারের সাথে সম্মতিযুক্ত sequ

এটি এমন কিছু ক্ষেত্রে অনুমতি দেয় যা আগে ইউবি হবে:

f(i = -1, i = -1); // value of i is -1
f(i = -1, i = -2); // value of i is either -1 or -2, but not specified which one

2
সি ++ 17 এর জন্য এই আপডেটটি যুক্ত করার জন্য আপনাকে ধন্যবাদ , তাই আমার করা হয়নি। ;)
ইয়াক্ক - অ্যাডাম নেভ্রামামন্ট

দুর্দান্ত, এই উত্তরের জন্য আপনাকে অনেক ধন্যবাদ। কিছুটা ফলোআপ: যদি fস্বাক্ষর f(int a, int b)থাকে তবে সি ++ 17 কি গ্যারান্টি দেয় a == -1এবং b == -2যদি দ্বিতীয় ক্ষেত্রে হিসাবে ডাকা হয়?
নিকু স্টির্ককা

হ্যাঁ. আমাদের যদি প্যারামিটার থাকে aএবং bতা-হয় হয় i-1- aএর পরে আরম্ভ করা হয় , তারপরে - iপরে- b-2, অথবা কাছাকাছি পথে আরম্ভ করা হয়। উভয় ক্ষেত্রে, আমরা দিয়ে শেষ a == -1এবং b == -2। অন্তত আমি এইভাবেই পড়ি " প্রতিটি সম্পর্কিত মান গণনা এবং পার্শ্ব প্রতিক্রিয়া সহ প্যারামিটারের সূচনাটি অনির্দিষ্টকালের জন্য অন্য যে কোনও প্যারামিটারের সাথে সম্মতিযুক্ত " "
আলেকসডি

আমি মনে করি এটি চিরকাল থেকে সি তে একই ছিল।
ফুজ

5

অ্যাসাইনমেন্ট অপারেটরটি ওভারলোড করা যায়, এক্ষেত্রে আদেশের বিষয়টি বিবেচনা করতে পারে:

struct A {
    bool first;
    A () : first (false) {
    }
    const A & operator = (int i) {
        first = !first;
        return * this;
    }
};

void f (A a1, A a2) {
    // ...
}


// ...
A i;
f (i = -1, i = -1);   // the argument evaluated first has ax.first == true

1
সত্যই যথেষ্ট, তবে প্রশ্নটি স্কেলারের ধরণ সম্পর্কে ছিল , যা অন্যরা মূলত অন্তর্নির্ভর পরিবার, ভাসমান পরিবার এবং পয়েন্টারগুলি বোঝায়।
নিকু স্টুর্কা

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

2

এটি কেবল "উত্তর দিচ্ছে না ইন্টি বা ফ্লোটের মতো" স্কেলার অবজেক্ট "এর অর্থ কী হতে পারে তা আমি নিশ্চিত নই"।

আমি "স্কেলার অবজেক্ট" কে "স্কেলার টাইপ অবজেক্ট" বা "স্কেলার টাইপ ভেরিয়েবল" এর সংক্ষেপণ হিসাবে ব্যাখ্যা করব। তারপরে pointer,enum (ধ্রুব) স্কালে ধরনের।

এটি স্কেলার টাইপের একটি এমএসডিএন নিবন্ধ ।


এটি "লিঙ্ক কেবল উত্তর" এর মতো কিছুটা পড়ে। আপনি কি এই উত্তর থেকে প্রাসঙ্গিক বিটগুলি অনুলিপি করতে পারেন (একটি ব্লককোটে)?
কোল জনসন

1
@ কোল জনসন এটি কেবল একটি লিঙ্ক উত্তর নয়। লিঙ্কটি কেবল আরও ব্যাখ্যার জন্য। আমার উত্তর "পয়েন্টার", "এনাম"।
পেং ঝাং

আমি বলিনি যে আপনার উত্তরটি কেবল একটি উত্তর ছিল । আমি বলেছিলাম " এটি [যেমন] পড়ছে" । আমি আপনাকে সহায়তা সেকশনে উত্তরগুলি কেন চাই না তা পড়ার পরামর্শ দিচ্ছি suggest কারণ হ'ল মাইক্রোসফ্ট যদি তাদের সাইটে তাদের ইউআরএল আপডেট করে তবে সেই লিঙ্কটি বিরতি।
কোল জনসন

1

আসলে, কম্পাইলার এটি যাচাই করবে তার উপর নির্ভর করার কোনও কারণ নেই i একই মানের সাথে দু'বার নির্ধারিত হয়েছে , যাতে এটি একক অ্যাসাইনমেন্টের সাথে প্রতিস্থাপন করা সম্ভব হয়। আমাদের যদি কিছু এক্সপ্রেশন থাকে?

void g(int a, int b, int c, int n) {
    int i;
    // hey, compiler has to prove Fermat's theorem now!
    f(i = 1, i = (ipow(a, n) + ipow(b, n) == ipow(c, n)));
}

1
ফেরামাতের উপপাদ্য প্রমাণ করার দরকার নেই: কেবলমাত্র নিয়োগ 1করুন i। উভয় যুক্তিই বরাদ্দ করে 1এবং এটি "সঠিক" জিনিসটি করে, বা আর্গুমেন্টগুলি বিভিন্ন মান দেয় এবং এটি অপরিবর্তিত আচরণ তাই আমাদের পছন্দটি এখনও অনুমোদিত।
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.