কেন এই নির্মাণগুলি পূর্ব এবং উত্তরোত্তর পূর্বনির্ধারিত আচরণ ব্যবহার করছে?


814
#include <stdio.h>

int main(void)
{
   int i = 0;
   i = i++ + ++i;
   printf("%d\n", i); // 3

   i = 1;
   i = (i++);
   printf("%d\n", i); // 2 Should be 1, no ?

   volatile int u = 0;
   u = u++ + ++u;
   printf("%d\n", u); // 1

   u = 1;
   u = (u++);
   printf("%d\n", u); // 2 Should also be one, no ?

   register int v = 0;
   v = v++ + ++v;
   printf("%d\n", v); // 3 (Should be the same as u ?)

   int w = 0;
   printf("%d %d\n", ++w, w); // shouldn't this print 1 1

   int x[2] = { 5, 8 }, y = 0;
   x[y] = y ++;
   printf("%d %d\n", x[0], x[1]); // shouldn't this print 0 8? or 5 0?
}

12
@ জ্যারেট, নাহ, "সিকোয়েন্স পয়েন্টস" এর জন্য কিছু পয়েন্টার দরকার ছিল। কাজ করার সময় আমি আই = আই ++ সহ একটি কোডের টুকরো পেয়েছি, আমি আপনাকে "এটি i এর মান পরিবর্তন করে না" বলে সম্বোধন করে। আমি পরীক্ষা করেছিলাম এবং আমি ভাবছিলাম কেন। যেহেতু, আমি এই বিধিটিকে সরিয়ে দিয়েছি এবং এটি ++ দ্বারা প্রতিস্থাপন করেছি;
পাইক্স

198
আমি মনে করি এটি আকর্ষণীয় যে সকলেই সর্বদা অনুমান করে যে এই জাতীয় প্রশ্ন জিজ্ঞাসা করা হয়েছে কারণ প্রশ্নকর্তা প্রশ্নে কাঠামোটি ব্যবহার করতে চান। আমার প্রথম অনুমান ছিল যে পাইকস জানে যে এগুলি খারাপ, তবে কৌতূহলজনক যে তারা যেভাবে যাহা সংকলক ব্যবহার করছিল সেগুলিতে তারা যেভাবে আচরণ করে ... এবং হ্যাঁ, কী বলা যায় না ... এটি অপরিজ্ঞাত, এটি কিছু করতে পারে। .. জেসিএফ সহ (জাম্প এবং ক্যাচ ফায়ার)
ব্রায়ান পোস্টো

32
আমি কৌতূহলী: কম্পাইলাররা কেন "u = u ++ + ++ u" এর মতো নির্মাণের বিষয়ে সতর্কতা বলে মনে হচ্ছে না; ফলাফল অপরিজ্ঞাত হলে?
ওপেনজিএল ইএস

5
(i++)এখনও প্রথম বন্ধনী নির্বিশেষে 1 এর মূল্যায়ন করে
ড্রু ম্যাকগউইন

2
যা i = (i++);কিছু করার ইচ্ছা ছিল, অবশ্যই এটি লেখার একটি পরিষ্কার উপায় আছে way এটি সঠিকভাবে সংজ্ঞায়িত করা হলেও সত্য হবে। এমনকি জাভাতেও যা আচরণের সংজ্ঞা দেয় i = (i++);, এটি এখনও খারাপ কোড bad কেবল লিখুনi++;
কিথ থমসন

উত্তর:


566

সি এর অপরিজ্ঞাত আচরণের ধারণা রয়েছে, অর্থাত্ কিছু ভাষা নির্মানগুলি সিনট্যাক্টিকভাবে বৈধ তবে কোডটি চালিত হওয়ার সময় আপনি আচরণটির পূর্বাভাস দিতে পারবেন না।

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

তাহলে, এই বিষয়টি মাথায় রেখেই কেন এই "সমস্যাগুলি"? ভাষাটি স্পষ্টভাবে বলেছে যে নির্দিষ্ট কিছু জিনিস অপরিবর্তিত আচরণের দিকে নিয়ে যায় । কোনও সমস্যা নেই, জড়িত কোনও "উচিত" নেই। জড়িত ভেরিয়েবলগুলির মধ্যে একটি ঘোষণার সাথে সাথে যদি অপরিবর্তিত আচরণ পরিবর্তন হয় volatileতবে তা প্রমাণিত বা কিছুই পরিবর্তন করে না। এটি অপরিজ্ঞাত ; আপনি আচরণ সম্পর্কে যুক্তি করতে পারবেন না।

আপনার সবচেয়ে আকর্ষণীয়-দৃষ্টান্ত, উদাহরণটি

u = (u++);

অপরিশোধিত আচরণের পাঠ্য-পুস্তকের উদাহরণ ( সিকোয়েন্স পয়েন্টগুলিতে উইকিপিডিয়ায় প্রবেশ ) দেখুন।


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

শুধু সবাইকে বিভ্রান্ত করার জন্য, এরকম কয়েকটি উদাহরণ এখন সি 11-এ ভালভাবে সংজ্ঞায়িত করা হয়েছে, যেমন i = ++i + 1;
এমএম

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

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

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

78

আপনার কোডের লাইনটি কেবল সংকলন এবং বিচ্ছিন্ন করুন, যদি আপনি এতটা ঝোঁক হন যে আপনি কী পাচ্ছেন তা ঠিক কীভাবে তা পেতে হবে।

আমার মেশিনে এটি যা হয় তা নিয়ে আমি যা ভাবছি তার সাথে একত্রে:

$ cat evil.c
void evil(){
  int i = 0;
  i+= i++ + ++i;
}
$ gcc evil.c -c -o evil.bin
$ gdb evil.bin
(gdb) disassemble evil
Dump of assembler code for function evil:
   0x00000000 <+0>:   push   %ebp
   0x00000001 <+1>:   mov    %esp,%ebp
   0x00000003 <+3>:   sub    $0x10,%esp
   0x00000006 <+6>:   movl   $0x0,-0x4(%ebp)  // i = 0   i = 0
   0x0000000d <+13>:  addl   $0x1,-0x4(%ebp)  // i++     i = 1
   0x00000011 <+17>:  mov    -0x4(%ebp),%eax  // j = i   i = 1  j = 1
   0x00000014 <+20>:  add    %eax,%eax        // j += j  i = 1  j = 2
   0x00000016 <+22>:  add    %eax,-0x4(%ebp)  // i += j  i = 3
   0x00000019 <+25>:  addl   $0x1,-0x4(%ebp)  // i++     i = 4
   0x0000001d <+29>:  leave  
   0x0000001e <+30>:  ret
End of assembler dump.

(আমি ... ধরুন যে 0x00000014 নির্দেশনাটি কোনও ধরণের সংকলক অপ্টিমাইজেশান ছিল?)


আমি কীভাবে মেশিনের কোড পাব? আমি ডে সি সি ++ ব্যবহার করি এবং সংকলক সেটিংসে আমি 'কোড জেনারেশন' বিকল্পটি নিয়ে
খেললাম

5
@ অর্ণিয়াকা gcc evil.c -c -o evil.binএবং gdb evil.bindisassemble evil, বা উইন্ডোজ সমতুল্য যাই হোক না কেন :)
Badp

21
এই উত্তরটি আসলে প্রশ্নের উত্তর দেয় না Why are these constructs undefined behavior?
শফিক ইয়াঘমুর

9
অন্যদিকে, সমাবেশ (সহ gcc -S evil.c) সংকলন করা সহজ হবে , যা এখানে এখানে প্রয়োজনীয় needed এটিকে জড়ো করে তা ছড়িয়ে দেওয়া এটির চারপাশের এক উপায়।
কেট

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

64

আমি মনে করি সি 99 স্ট্যান্ডার্ডের প্রাসঙ্গিক অংশগুলি 6.5 এক্সপ্রেশন, §2

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

এবং 6.5.16 অ্যাসাইনমেন্ট অপারেটর, §4:

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


2
উপরেরটি কি বোঝায় যে 'i = i = 5; "হবে অপরিজ্ঞাত আচরণ?
সুপারক্যাট

1
@ সুপ্যাক্যাট যতদূর আমি জানি i=i=5এটিও
অপরিজ্ঞাত

2
@ জাইবিস: বেশিরভাগ জায়গার নিয়মের জন্য আমি যে যুক্তিটি ব্যবহার করতে চাই তা প্রয়োগ করে যে তাত্ত্বিকভাবে একটি মুতলি-প্রসেসর প্ল্যাটফর্ম A=B=5;"লিখন-লক এ; রাইটিং-লক বি; স্টোর 5 থেকে এ; স্টোর 5 থেকে বি; আনলক বি" এর মতো কিছু বাস্তবায়িত করতে পারে ; আনলক এ; ", এবং C=A+B;" রিড-লক এ; রিড-লক বি; গণনা এ + বি; আনলক এ এবং বি; লিখন-লক সি; স্টোর ফলাফল; আনলক সি; "এর মতো একটি বিবৃতি । এটি নিশ্চিত করবে যে যদি একটি থ্রেড কাজ করে A=B=5;এবং অন্যটি C=A+B;পরে থ্রেড হয় তবে উভয়ই উভয় রচনাকে স্থান পেয়েছে বা উভয়ই দেখতে পাবে। সম্ভবত একটি দরকারী গ্যারান্টি। যদি একটি থ্রেড করেনি I=I=5;, কিন্তু, ...
supercat

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

1
@ সুপের্যাট তবে কেবল সি 99 এর সিকোয়েন্স পয়েন্ট অ্যাক্সেস রুল কি এটিকে অপরিজ্ঞাত আচরণ হিসাবে ঘোষণা করার পক্ষে যথেষ্ট হবে না? সুতরাং এটি প্রযুক্তিগতভাবে হার্ডওয়্যার বাস্তবায়ন করতে পারে কি আসে যায় না?
dhein

55

সি স্ট্যান্ডার্ড থেকে উদ্ধৃত এখানে বেশিরভাগ উত্তর এই জোর দিয়ে জোর দিয়েছিল যে এই নির্মাণগুলির আচরণ অপরিজ্ঞাত। এই কনস্ট্রাক্টগুলির আচরণটি কেন অপরিবর্তিত তা বোঝার জন্য আসুন প্রথমে এই শর্তাদি C11 স্ট্যান্ডার্ডের আলোকে বুঝতে পারি:

সিকোয়েন্সড: (5.1.2.3)

যে কোনও দুটি মূল্যায়ন দেওয়া হয়েছে Aএবং Bযদি Aআগে ধারাবাহিকভাবে হয় B, তবে কার্যকর করা কার্যকর Aহবে B

Unsequenced:

যদি Aআগে বা পরে সিকোয়েন্সড না হয় Bতবে তা Aএবং Bঅনিচ্ছাকৃত।

মূল্যায়ন দুটি জিনিসের মধ্যে একটি হতে পারে:

  • মান গণনা , যা একটি এক্সপ্রেশন ফলাফল কাজ করে; এবং
  • পার্শ্ব প্রতিক্রিয়া , যা বস্তুর পরিবর্তন mod

সিকোয়েন্স পয়েন্ট:

এক্সপ্রেশন মূল্যায়ন মধ্যে একটা ক্রম বিন্দু উপস্থিতিতে Aএবং Bযে বোঝা যে মান গণনার এবং পার্শ্ব প্রতিক্রিয়া সঙ্গে যুক্ত Aপ্রত্যেক আগে সিকোয়েন্স করা হয় মান গণনার এবং পার্শ্ব প্রতিক্রিয়া সঙ্গে যুক্ত B

এখন প্রশ্নে আসা মত, মত প্রকাশের জন্য

int i = 1;
i = i++;

স্ট্যান্ডার্ড বলে যে:

.5.৫ এক্সপ্রেশন:

স্কেলের বস্তুর উপর একটি পার্শ্ব প্রতিক্রিয়া থেকে unsequenced আপেক্ষিক হলে হয় একই স্কালে বস্তুর উপর একটি ভিন্ন পার্শ্ব প্রতিক্রিয়া অথবা একটি মান গণনা একই স্কালে বস্তুর মান ব্যবহার করে, আচরণ অনির্দিষ্ট হয় । [...]

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

iঅ্যাসাইনমেন্টের বামদিকে এবং অ্যাসাইনমেন্টের ilডানদিকে (এক্সপ্রেশনটিতে i++) এর নাম পরিবর্তন করা যাক ir, তাহলে এক্সপ্রেশনটি এর মতো হতে পারে

il = ir++     // Note that suffix l and r are used for the sake of clarity.
              // Both il and ir represents the same object.  

পোস্টফিক্স ++অপারেটর সম্পর্কিত একটি গুরুত্বপূর্ণ বিষয় হ'ল:

মাত্র কারণ ++আসে পরে পরিবর্তনশীল অর্থ এই নয় যে বৃদ্ধি প্রয়াত ঘটে । সংকলকটি যতক্ষণ পছন্দ করবে ততক্ষণ ইনক্রিমেন্টটি ঘটতে পারে যতক্ষণ না সংকলকটি নিশ্চিত করে যে মূল মানটি ব্যবহৃত হয়েছে

এর অর্থ হল অভিব্যক্তিটি il = ir++হিসাবে হিসাবে মূল্যায়ন করা যেতে পারে

temp = ir;      // i = 1
ir = ir + 1;    // i = 2   side effect by ++ before assignment
il = temp;      // i = 1   result is 1  

অথবা

temp = ir;      // i = 1
il = temp;      // i = 1   side effect by assignment before ++
ir = ir + 1;    // i = 2   result is 2  

দুটি পৃথক ফলাফলের ফলস্বরূপ 1এবং 2যা অ্যাসাইনমেন্ট দ্বারা পার্শ্ব প্রতিক্রিয়াগুলির ক্রমের উপর নির্ভর করে ++এবং তাই ইউবিকে অনুরোধ করে।


52

আচরণ সত্যিই কারণ এটি উভয় ডাকে ব্যাখ্যা করা সম্ভব নয় অনির্দিষ্ট আচরণ এবং অনির্ধারিত আচরণ , তাই আমরা এই কোড সম্পর্কে কোনো সাধারণ ভবিষ্যৎবাণী করতে পারবেন না, যদিও যদি আপনি পড়তে Olve Maudal এর যেমন কাজ ডীপ সি এবং অনির্দিষ্ট ও অনির্ধারিত কখনও কখনও আপনি ভাল করতে পারেন একটি নির্দিষ্ট সংকলক এবং পরিবেশের সাথে খুব নির্দিষ্ট ক্ষেত্রে অনুমান করে তবে দয়া করে উত্পাদনের কাছাকাছি কোথাও এটি করবেন না।

সুতরাং অনির্দিষ্ট আচরণের দিকে এগিয়ে যাওয়া , খসড়া c99 স্ট্যান্ডার্ড বিভাগের 6.5অনুচ্ছেদে 3 ( জোর দেওয়া খনি ) বলেছেন :

অপারেটর এবং অপারেটরগুলির গোষ্ঠীকরণটি সিনট্যাক্স দ্বারা সূচিত হয় 74৪) পরে নির্দিষ্ট করা (ফাংশন-কল (), &&, ||,?:, এবং কমা অপারেটরদের জন্য) বাদে, সুব্যাপ্রেসেশনগুলির মূল্যায়নের ক্রম এবং ক্রমটির আদেশ কোন পার্শ্ব প্রতিক্রিয়া হয় তা উভয়ই অনির্ধারিত।

সুতরাং যখন আমাদের মতো একটি লাইন থাকবে:

i = i++ + ++i;

আমরা কিনা জানি না i++বা ++iপ্রথম মূল্যায়ন করা হবে। এটি মূলত সংকলকটিকে অপ্টিমাইজেশনের জন্য আরও ভাল বিকল্পগুলি দেওয়া

আমরা আছে অনির্ধারিত আচরণ থেকে প্রোগ্রাম ভেরিয়েবল পরিবর্তন করা হয় (এখানে পাশাপাশি i, uমধ্যে একবারের, ইত্যাদি ..) আরো ক্রম পয়েন্ট । খসড়া স্ট্যান্ডার্ড বিভাগের 6.5অনুচ্ছেদ 2 ( জোর খনি ) থেকে:

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

এটি নিম্নলিখিত কোড উদাহরণগুলি অপরিজ্ঞাপিত হিসাবে উদ্ধৃত করেছে:

i = ++i + 1;
a[i++] = i; 

এই সমস্ত উদাহরণে কোডটি একই সিকোয়েন্স পয়েন্টে একবারে একাধিকবার কোনও বস্তুর সংশোধন করার চেষ্টা করছে, যা ;প্রতিটি ক্ষেত্রে এর সাথে শেষ হবে :

i = i++ + ++i;
^   ^       ^

i = (i++);
^    ^

u = u++ + ++u;
^   ^       ^

u = (u++);
^    ^

v = v++ + ++v;
^   ^       ^

বিভাগে খসড়া সি 99 স্ট্যান্ডার্ডে অনির্দিষ্ট আচরণের সংজ্ঞা দেওয়া হয়েছে 3.4.4:

একটি অনির্ধারিত মান, বা অন্য আচরণের ব্যবহার যেখানে এই আন্তর্জাতিক স্ট্যান্ডার্ডটি দুই বা ততোধিক সম্ভাবনা সরবরাহ করে এবং কোনও প্রয়োজনে কোন প্রয়োজনে বেছে নেওয়া হয়েছে তার জন্য আরও কোনও প্রয়োজনীয়তা চাপায় না

এবং অপরিজ্ঞাত আচরণটি বিভাগে সংজ্ঞায়িত করা হয়েছে 3.4.3:

আচরণ, একটি ননপোর্টেবল বা ভ্রান্ত প্রোগ্রাম নির্মাণ বা ভুল তথ্য ব্যবহারের উপর, যার জন্য এই আন্তর্জাতিক স্ট্যান্ডার্ড কোনও প্রয়োজনীয়তা আরোপ করে না

এবং নোট যে:

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


33

এর উত্তর দেওয়ার আরেকটি উপায়, ক্রম বিন্দু এবং অপরিজ্ঞাত আচরণের তীব্র বিবরণে জড়িয়ে পড়ার চেয়ে কেবল জিজ্ঞাসা করা, তাদের কী বোঝাতে চাইবে ? প্রোগ্রামার কি করতে চেষ্টা করছিল?

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

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

i = i + 1

সি এর অবশ্যই একটি সহজ শর্টকাট রয়েছে:

i++

এর অর্থ, "আইতে 1 যোগ করুন এবং ফলাফলটি আইতে ফিরিয়ে দিন"। সুতরাং যদি আমরা দুজনের একটি হজপড নির্মাণ করি, লিখে

i = i++

আমরা আসলে যা বলছি তা হ'ল "আমার সাথে 1 যুক্ত করুন, এবং ফলাফলটিকে আমি আবার অর্পণ করবো, এবং ফলাফলটি আবার আইনে অর্পণ করব"। আমরা বিভ্রান্ত, তাই কম্পাইলারটিও যদি বিভ্রান্ত হয় তবে এটি আমাকে খুব বেশি বিরক্ত করবেন না।

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

আমরা comp.lang.c এ অজানা ঘন্টা ব্যয় করতাম এবং এগুলি কেন অপরিবর্তিত তা নিয়ে আলোচনা করে । আমার দীর্ঘ দুটি উত্তর, এটি ওয়েবে সংরক্ষণাগারভুক্ত কেন তা সত্যই ব্যাখ্যা করার চেষ্টা করুন:

সি এফএকিউ তালিকার 3 নং বিভাগের প্রশ্ন 3.8 এবং বাকি প্রশ্নগুলিও দেখুন ।


1
অনির্ধারিত আচরণ সংক্রান্ত বরং কদর্য gotcha হয় যে যখন এটা ব্যবহার করা কম্পাইলার এর 99.9% ব্যবহার করার জন্য নিরাপদ হতে *p=(*q)++;মানে if (p!=q) *p=(*q)++; else *p= __ARBITRARY_VALUE;যে এখন আর তা নেই। হাইপার-মডার্নিয়াল সি'র সাথে আধুনিকীকরণের মতো কিছু লেখার প্রয়োজন ছিল (যদিও কোডটি নির্দেশ করার কোনও মানসম্মত উপায় নেই যা রয়েছে তা বিবেচনা করে না *p) প্রাক্তনকে সরবরাহ elseকরার জন্য ব্যবহৃত দক্ষতা সংযোজনকারীদের স্তরটি অর্জন করার জন্য ( ধারাটি প্রয়োজনীয় হওয়ার জন্য প্রয়োজনীয়) সংকলকটি আরও ifকিছু নতুন সংকলকগুলির প্রয়োজন পড়বে optim
সুপারক্যাট

@ সুপের্যাট আমি এখন বিশ্বাস করি যে এই ধরণের অপ্টিমাইজেশান সম্পাদনের জন্য যথেষ্ট "স্মার্ট" যে কোনও সংকলক অবশ্যই assertবিবৃতিতে উঁকি দেওয়ার জন্য যথেষ্ট স্মার্ট হতে হবে , যাতে প্রোগ্রামার একটি সাধারণ প্রশ্নে প্রশ্নটির রেখার আগে যেতে পারে assert(p != q)। (অবশ্যই, এই কোর্সটি গ্রহণের <assert.h>জন্য নন-ডিবাগ সংস্করণগুলিতে সরাসরি দাবিগুলি মুছে ফেলার জন্য পুনর্লিখনের প্রয়োজন হবে , বরং তাদেরকে এমন কিছুতে পরিণত করুন __builtin_assert_disabled()যা সংকলকটি যথাযথভাবে দেখতে পারে, এবং তার জন্য কোড নির্গমন নয় not)
স্টিভ সামিট

25

প্রায়শই এই প্রশ্নটি কোডের মতো সম্পর্কিত প্রশ্নের সদৃশ হিসাবে যুক্ত হয়

printf("%d %d\n", i, i++);

অথবা

printf("%d %d\n", ++i, i++);

বা অনুরূপ রূপগুলি।

যদিও এটি ইতিমধ্যে বর্ণিত হিসাবে নির্ধারিত আচরণ, যদিও printf()কোনও বিবৃতিটির সাথে তুলনা করার সময় জড়িত থাকে তখন সূক্ষ্ম পার্থক্য থাকে :

x = i++ + i++;

নিম্নলিখিত বিবৃতিতে:

printf("%d %d\n", ++i, i++);

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

সংযুক্ত জে, অনির্দিষ্ট আচরণগুলি ors

ক্রমের ক্রম (6.5.2.2) মধ্যে ক্রিয়াকলাপের ডিজাইনার, যুক্তি এবং আর্গুমেন্টের মধ্যে subexpressions ক্রম মূল্যায়ন করা হয় যা।

3.4.4, অনির্দিষ্ট আচরণ

একটি অনির্ধারিত মান, বা অন্য আচরণের ব্যবহার যেখানে এই আন্তর্জাতিক স্ট্যান্ডার্ডটি দুই বা ততোধিক সম্ভাবনা সরবরাহ করে এবং কোনও প্রয়োজনে কোন প্রয়োজনে বেছে নেওয়া হয়েছে তার জন্য আর কোনও প্রয়োজনীয়তা চাপায় না।

উদাহরণ অনির্দিষ্ট আচরণের একটি উদাহরণ হ'ল ক্রমটির পক্ষে যুক্তিগুলি মূল্যায়ন করা হয়।

অনির্দিষ্ট আচরণ নিজেই একটি সমস্যা হয় না। এই উদাহরণ বিবেচনা করুন:

printf("%d %d\n", ++x, y++);

এই অত্যন্ত হয়েছে অনির্দিষ্ট আচরণ কারণ মূল্যায়ন ক্রম ++xএবং y++অনির্দিষ্ট হয়। তবে এটি পুরোপুরি আইনী এবং বৈধ বিবৃতি। আছে কোন এই বিবৃতিতে অনির্ধারিত আচরণ। কারণ পরিবর্তনগুলি ( ++xএবং y++) পৃথক বস্তুগুলিতে করা হয়।

কি নিম্নলিখিত বিবৃতি রেন্ডার করে

printf("%d %d\n", ++i, i++);

যেমন অনির্ধারিত আচরণ সত্য যে এই দুটি এক্সপ্রেশন পরিবর্তন হয় একই বস্তুর iএকটি হস্তক্ষেপ ছাড়া ক্রম বিন্দু


আরেকটি বিশদটি হ'ল প্রিন্টফ () কলের সাথে জড়িত কমাটি বিভাজক , কমা অপারেটর নয়

এটি একটি গুরুত্বপূর্ণ পার্থক্য কারণ কমা অপারেটর তাদের অপারেশনগুলির মূল্যায়নের মধ্যে একটি ক্রম বিন্দু প্রবর্তন করে যা নিম্নলিখিতটি আইনী করে তোলে:

int i = 5;
int j;

j = (++i, i++);  // No undefined behaviour here because the comma operator 
                 // introduces a sequence point between '++i' and 'i++'

printf("i=%d j=%d\n",i, j); // prints: i=7 j=6

কমা অপারেটর তার অপারেশনগুলি বাম থেকে ডানে মূল্যায়ন করে এবং কেবল সর্বশেষ অপারেন্ডের মান দেয়। সুতরাং j = (++i, i++);, ++iবাড়তি iকরার 6এবং i++উৎপাদনের পুরোনো মান i( 6) যা নির্ধারিত হয় j। তারপরে পোস্ট-ইনক্রিমেন্টের কারণে iহয়ে যায় 7

সুতরাং যদি ফাংশন কল এ কমা যদি কমা অপারেটর হতে হয়

printf("%d %d\n", ++i, i++);

কোন সমস্যা হবে না কিন্তু এটা এমন কিছুকে ডাকে, অনির্ধারিত আচরণ কারণ কমা এখানে একটি হল বিভাজক


যারা অপরিজ্ঞাত আচরণের ক্ষেত্রে নতুন তাদের ক্ষেত্রে সি- র ধারণা এবং অন্যান্য অপরিবর্তিত আচরণের অন্যান্য বিভিন্ন রূপগুলি বুঝতে প্রতিটি সি প্রোগ্রামারকে অপরিজ্ঞাত আচরণ সম্পর্কে কী জানা উচিত তা পড়ার দ্বারা উপকৃত হবেন For

এই পোস্ট: অপরিজ্ঞাত, অনির্ধারিত এবং প্রয়োগ-সংজ্ঞায়িত আচরণটিও প্রাসঙ্গিক।


এই ক্রমটি int a = 10, b = 20, c = 30; printf("a=%d b=%d c=%d\n", (a = a + b + c), (b = b + b), (c = c + c));স্থিতিশীল আচরণ হিসাবে প্রদর্শিত হবে (gcc v7.3.0 এ ডান থেকে বাম আর্গুমেন্ট মূল্যায়ন; ফলাফল "a = 110 বি = 40 সি = 60")। অ্যাসাইনমেন্টগুলিকে 'পূর্ণ বিবৃতি' হিসাবে বিবেচনা করা হয় এবং এইভাবে একটি ক্রম বিন্দুটি পরিচয় করিয়ে দেওয়ার কারণে এটি হয়? বাম-থেকে-ডান যুক্তি / বিবৃতি মূল্যায়নের ফলাফলটি হওয়া উচিত নয়? বা, এটি কি কেবল অপরিবর্তিত আচরণের প্রকাশ?
কাওয়াদিয়াস

@ কাভাদিয়াস যে প্রিন্টফের বিবৃতিতে একই কারণে উপরোক্ত ব্যাখ্যা দেওয়া হয়েছে, সংজ্ঞায়িত আচরণ জড়িত। আপনি যথাক্রমে তৃতীয় ও চতুর্থ যুক্তি লিখছেন bএবং c২ য় যুক্তিতে পড়ছেন। তবে এই এক্সপ্রেশনগুলির মধ্যে কোনও ক্রম নেই (২ য়, তৃতীয়, এবং চতুর্থ আরগস)। জিসিসি / কলংয়ের একটি বিকল্প রয়েছে -Wsequence-pointযা এগুলি সন্ধান করতেও সহায়তা করতে পারে।
পিপি

23

যদিও কোনও সংকলক এবং প্রসেসর প্রকৃতপক্ষে এটি করবে এটি অসম্ভব, যদিও সি স্ট্যান্ডার্ডের অধীনে, "আই ++" সিকোয়েন্স সহ বাস্তবায়িত করা আইনী হবে:

In a single operation, read `i` and lock it to prevent access until further notice
Compute (1+read_value)
In a single operation, unlock `i` and store the computed value

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

যদি সংকলকটি i++উপরে বর্ণিত (মান অনুসারে আইনী) লিখিতভাবে লিখতে থাকে এবং সামগ্রিক অভিব্যক্তিটির মূল্যায়ন জুড়ে উপরোক্ত নির্দেশাবলীর ছেদ করছিল (এছাড়াও আইনী), এবং যদি এটি লক্ষ্য না ঘটে যে অন্য নির্দেশাবলীর মধ্যে একটি ঘটেছে অ্যাক্সেস করার iজন্য, সংকলকটির পক্ষে নির্দেশাবলীর ক্রম তৈরি করা (এবং আইনী) সম্ভব হবে যা অচলাবস্থার হবে। নিশ্চিত হওয়ার জন্য, একটি সংকলক প্রায় একই ক্ষেত্রে সমস্যাটি সনাক্ত করতে পারে যেখানে একই ভেরিয়েবল iউভয় স্থানে ব্যবহৃত হয়, তবে যদি কোনও রুটিন দুটি পয়েন্টার pএবং q, এবং ব্যবহার (*p)এবং (*q)উপরের এক্সপ্রেশনটিতে উল্লেখ ব্যবহার করে (ব্যবহার না করে)iদ্বিগুণ) সংকলকটির অচলাবস্থাটি সনাক্ত করতে বা এড়ানোর দরকার পড়বে না যদি একই বস্তুর ঠিকানা উভয়ের জন্য পাস করা হয় pএবং q


16

যদিও সিনট্যাক্স অভিব্যক্তির পছন্দ a = a++বা a++ + a++বৈধ, আচরণ এই নির্মানের হয় অনির্দিষ্ট কারণে হইবে সি মান আনুগত্য করা হয় না। C99 6.5p2 :

  1. পূর্ববর্তী এবং পরবর্তী সিকোয়েন্স পয়েন্টের মধ্যে একটি অবজেক্টের মূল্যায়নের মাধ্যমে কোনও বস্তুর তার সঞ্চিত মানটি একবারে পরিবর্তিত হবে। []২] তদ্ব্যতীত, পূর্ববর্তী মানটি কেবলমাত্র সংরক্ষণ করা হবে তা নির্ধারণ করতেই পড়তে হবে []৩]

সঙ্গে পাদটীকা 73 আরও সে বিষয়ে পরিষ্কারভাবে বর্ণনা করে

  1. এই অনুচ্ছেদ যেমন অপরিজ্ঞাত বিবৃতি প্রকাশকে রেন্ডার করে

    i = ++i + 1;
    a[i++] = i;

    অনুমতি দেওয়ার সময়

    i = i + 1;
    a[i] = i;

বিভিন্ন সিকোয়েন্স পয়েন্টগুলি সি 11 এর আনেক্সেক্স সিতে তালিকাভুক্ত করা হয়েছে (এবং সি 99 ):

  1. নীচে 5.1.2.3 এ বর্ণিত ক্রম পয়েন্টগুলি রয়েছে:

    • ফাংশন ডিজাইনারের মূল্যায়ন এবং একটি ফাংশন কল এবং আসল কলটিতে প্রকৃত যুক্তিগুলির মধ্যে। (6.5.2.2)।
    • নিম্নলিখিত অপারেটরগুলির প্রথম এবং দ্বিতীয় অপারেশনগুলির মূল্যায়নের মধ্যে: লজিকাল এ্যান্ড অ্যান্ড অ্যান্ড& (6.5.13); লজিকাল ওআর || (6.5.14); কমা, (6.5.17)।
    • শর্তসাপেক্ষে প্রথম অপারেন্ডের মূল্যায়নগুলির মধ্যে? : দ্বিতীয় এবং তৃতীয় অপারেটরগুলির অপারেটর এবং যে কোনওটির মূল্যায়ন করা হয় (6.5.15)।
    • পূর্ণ ঘোষণাকারীর সমাপ্তি: ঘোষক (6.7.6);
    • একটি সম্পূর্ণ এক্সপ্রেশন এবং পরবর্তী পূর্ণ এক্সপ্রেশন মূল্যায়নের মধ্যে মূল্যায়নের মধ্যে। নিম্নলিখিত সম্পূর্ণ এক্সপ্রেশন: একটি ইনিশিয়ালাইজার যা যৌগিক আক্ষরিক (6.7.9) অংশ নয়; একটি অভিব্যক্তি বিবৃতিতে প্রকাশ (6.8.3); একটি নির্বাচনের বিবৃতিটির নিয়ন্ত্রণকারী অভিব্যক্তি (যদি বা স্যুইচ করুন) (6.8.4); কিছুক্ষণ বা কর স্টেটমেন্টের নিয়ন্ত্রক প্রকাশ (6.8.5); বিবৃতি (6.8.5.3) জন্য একটি এর প্রতিটি (alচ্ছিক) এক্সপ্রেশন; রিটার্ন স্টেটমেন্টে (inচ্ছিক) প্রকাশ (6.8.6.4)।
    • অবিলম্বে কোনও লাইব্রেরির ফাংশন ফিরে আসার আগে (7.1.4)।
    • প্রতিটি ফর্ম্যাট ইনপুট / আউটপুট ফাংশন রূপান্তর নির্দিষ্টকরণের সাথে সম্পর্কিত ক্রিয়াগুলির পরে (.2.২১.,, .2.২৯.২)।
    • তুলনামূলক ফাংশনে প্রতিটি কল করার আগে এবং তাত্ক্ষণিকভাবে এবং তত্ক্ষণা ফাংশনে যে কোনও কল এবং সেই কলটির (7.22.5) আর্গুমেন্ট হিসাবে পাস হওয়া বস্তুর যে কোনও চলনের মধ্যেও।

সি 11 তে একই অনুচ্ছেদের শব্দটি হ'ল:

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

আপনি একটি প্রোগ্রামে যেমন ত্রুটিগুলি সনাক্ত করতে পারেন উদাহরণস্বরূপ -Wallএবং এর সাথে জিসিসির একটি সাম্প্রতিক সংস্করণ ব্যবহার করে -Werrorএবং তারপরে জিসিসি সরাসরি আপনার প্রোগ্রামটি সংকলন করতে অস্বীকার করবে। নিম্নলিখিতটি জিসিসির আউটপুট (উবুন্টু 6.2.0-5ubuntu12) 6.2.0 20161005:

% gcc plusplus.c -Wall -Werror -pedantic
plusplus.c: In function main’:
plusplus.c:6:6: error: operation on i may be undefined [-Werror=sequence-point]
    i = i++ + ++i;
    ~~^~~~~~~~~~~
plusplus.c:6:6: error: operation on i may be undefined [-Werror=sequence-point]
plusplus.c:10:6: error: operation on i may be undefined [-Werror=sequence-point]
    i = (i++);
    ~~^~~~~~~
plusplus.c:14:6: error: operation on u may be undefined [-Werror=sequence-point]
    u = u++ + ++u;
    ~~^~~~~~~~~~~
plusplus.c:14:6: error: operation on u may be undefined [-Werror=sequence-point]
plusplus.c:18:6: error: operation on u may be undefined [-Werror=sequence-point]
    u = (u++);
    ~~^~~~~~~
plusplus.c:22:6: error: operation on v may be undefined [-Werror=sequence-point]
    v = v++ + ++v;
    ~~^~~~~~~~~~~
plusplus.c:22:6: error: operation on v may be undefined [-Werror=sequence-point]
cc1: all warnings being treated as errors

গুরুত্বপূর্ণ অংশ জানা কি একটা ক্রম বিন্দু - এবং কি একটা ক্রম বিন্দু এবং কি নয় । উদাহরণস্বরূপ কমা অপারেটর একটি সিকোয়েন্স পয়েন্ট, তাই

j = (i ++, ++ i);

সুস্পষ্টভাবে সংজ্ঞায়িত করা হয়েছে, এবং iপুরানো মানটি ফলন করে একের সাথে বৃদ্ধি পাবে , সেই মানটি বাতিল করুন; তারপরে কমা অপারেটরে, পার্শ্ব প্রতিক্রিয়াগুলি নিষ্পত্তি করুন; এবং তারপরে iএকের জন্য বৃদ্ধি , এবং ফলস্বরূপ মানটি অভিব্যক্তির মান হয়ে যায় - যেমন এটি লেখার কেবল একটি স্বীকৃত উপায় j = (i += 2)যা আবার লেখার "চালাক" উপায় is

i += 2;
j = i;

যাইহোক, ,ফাংশন যুক্তি তালিকা রয়েছে না একটি কমা অপারেটর, এবং স্বতন্ত্র আর্গুমেন্ট মূল্যায়ন মধ্যে কোন ক্রম বিন্দু আছে; পরিবর্তে তাদের মূল্যায়ন একে অপরের সাথে সম্পর্কিত হয়। সুতরাং ফাংশন কল

int i = 0;
printf("%d %d\n", i++, ++i, i);

হয়েছে অনির্ধারিত আচরণ কারণ মূল্যায়ন মধ্যে কোন ক্রম বিন্দু আছে i++এবং ++iফাংশন আর্গুমেন্ট মধ্যে , এবং এর মান iতাই উভয় দ্বারা, দুইবার রুপান্তরিত করা হয়েছে i++এবং ++iপূর্ববর্তী এবং পরবর্তী ক্রম বিন্দু মধ্যে।


14

সি স্ট্যান্ডার্ড বলে যে একটি ভেরিয়েবল কেবলমাত্র দুটি সিকোয়েন্স পয়েন্টের মধ্যে একবারে নির্ধারিত হওয়া উচিত। উদাহরণস্বরূপ একটি আধা-কোলন একটি সিকোয়েন্স পয়েন্ট।
সুতরাং ফর্ম প্রতিটি বিবৃতি:

i = i++;
i = i++ + ++i;

এবং তাই এই নিয়ম লঙ্ঘন। মানটি আরও বলেছে যে আচরণটি অনির্ধারিত এবং অনির্দিষ্ট নয়। কিছু সংকলক এগুলি সনাক্ত করে এবং কিছু ফলাফল তৈরি করে তবে এটি স্ট্যান্ডার্ড অনুযায়ী হয় না।

তবে দুটি সিকোয়েন্স পয়েন্টের মধ্যে দুটি পৃথক ভেরিয়েবল বাড়ানো যেতে পারে।

while(*src++ = *dst++);

স্ট্রিংগুলি অনুলিপি / বিশ্লেষণ করার সময় উপরেরটি একটি সাধারণ কোডিং অনুশীলন।


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

11

ইন /programming/29505280/incrementing-array-index-in-c কেউ মত একটি বিবৃতি সম্পর্কে জিজ্ঞেস করেন:

int k[] = {0,1,2,3,4,5,6,7,8,9,10};
int i = 0;
int num;
num = k[++i+k[++i]] + k[++i];
printf("%d", num);

যা 7 প্রিন্ট করে ... ওপি 6 টি মুদ্রণ করবে বলে আশা করেছিল।

++iবাড়তি গণনার বাকি আগে সব সম্পূর্ণ নিশ্চয়তা নেই। আসলে, বিভিন্ন সংকলক এখানে বিভিন্ন ফলাফল পাবেন different উদাহরণস্বরূপ আপনার দেওয়া, প্রথম 2 ++iমৃত্যুদন্ড কার্যকর, তারপর মান k[]পড়তে হয় তবে, শেষ ++iতারপর k[]

num = k[i+1]+k[i+2] + k[i+3];
i += 3

আধুনিক সংকলকগুলি এটি খুব ভালভাবে অনুকূলিত করবে। প্রকৃতপক্ষে, আপনি মূলত যে কোডটি লিখেছিলেন তার চেয়ে সম্ভবত সম্ভবত এটি ভাল (ধরে নিয়েছি যে আপনি যেভাবে প্রত্যাশা করেছিলেন সেভাবে কাজ করেছিল)।


5

এই ধরণের গণনায় কী ঘটে যায় সে সম্পর্কে একটি ভাল ব্যাখ্যা আইএসও ডাব্লু 14 সাইট থেকে ন 1111 নথিতে সরবরাহ করা হয়েছে ।

আমি ধারনা ব্যাখ্যা।

এই পরিস্থিতিতে প্রযোজ্য স্ট্যান্ডার্ড আইএসও 9899 এর প্রধান নিয়মটি 6.5p2 p

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

মত প্রকাশের ক্রম পয়েন্টগুলি i=i++এর আগে i=এবং পরে রয়েছে i++

আমি উপরে যে কাগজটি উদ্ধৃত করেছিলাম তাতে ব্যাখ্যা করা হয়েছে যে আপনি প্রোগ্রামটি ছোট বাক্সগুলির দ্বারা গঠিত হিসাবে চিহ্নিত করতে পারবেন, প্রতিটি বাক্সে পর পর ২ টি ক্রমিক পয়েন্টের মধ্যে নির্দেশাবলী রয়েছে। সিকোয়েন্স পয়েন্টগুলি স্ট্যান্ডার্ডের আনেক্সেক্স সিতে সংজ্ঞায়িত করা হয়, এর ক্ষেত্রে i=i++2 টি সিকোয়েন্স পয়েন্ট রয়েছে যা একটি পূর্ণ-এক্সপ্রেশনকে সীমানা দেয়। এ জাতীয় অভিব্যক্তি expression-statementব্যাকরণের ব্যাকাস-নওর ফর্মের প্রবেশের সাথে সিন্ট্যাক্টিকভাবে সমতুল্য (একটি ব্যাকরণটি স্ট্যান্ডার্ডের এনেেক্স এ এ সরবরাহ করা হয়)।

সুতরাং একটি বাক্সের ভিতরে নির্দেশাবলীর ক্রমের কোনও স্পষ্ট অর্ডার নেই।

i=i++

হিসাবে ব্যাখ্যা করা যেতে পারে

tmp = i
i=i+1
i = tmp

বা হিসাবে

tmp = i
i = tmp
i=i+1

কোড ব্যাখ্যা করার জন্য এই i=i++উভয় ফর্মই বৈধ এবং উভয়ই বিভিন্ন উত্তর উত্পন্ন করার কারণে আচরণটি অপরিজ্ঞাত।

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

সম্পাদনা করুন:

এই ধরনের অস্পষ্টতা ব্যাখ্যা করার জন্য অন্যান্য ভাল উত্স হ'ল সি এবং ফ্যাক্ট সাইট (এছাড়াও এটি একটি বই হিসাবে প্রকাশিত ) এর এন্ট্রিগুলি হ'ল , এখানে এবং এখানে এবং এখানে


কীভাবে এই উত্তরটি বিদ্যমান উত্তরে নতুন যুক্ত হল? এছাড়াও এর জন্য ব্যাখ্যাগুলি এই উত্তরটিরi=i++ সাথে খুব মিল ।
হ্যাক

@ হ্যাকস আমি অন্যান্য উত্তরগুলি পড়িনি। আমি আইএসও 9899 ওপেন -std.org/jtc1/sc22/wg14/www/docs/n1188.pdf
alinsoar

5

আপনার প্রশ্নটি সম্ভবত ছিল না, "কেন সিগুলিতে এইগুলি নির্ধারিত আচরণ করা হয়?"। আপনার প্রশ্ন সম্ভবত ছিল, "কেন এই কোডটি (ব্যবহার করে ++) আমাকে প্রত্যাশিত মূল্য দেয় নি?", এবং কেউ আপনার প্রশ্নটিকে সদৃশ হিসাবে চিহ্নিত করেছে এবং আপনাকে এখানে পাঠিয়েছে।

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

আমি ধরে নিয়েছি আপনি এখনই সি ++এবং --অপারেটরগুলির প্রাথমিক সংজ্ঞা শুনেছেন এবং উপসর্গ ফর্মটি কীভাবে ++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. যদি এমন একটি পরিবর্তনশীল থাকে যা দুটি বা আরও বেশি জায়গায় সংশোধিত হয়ে থাকে (নির্ধারিত হয়) তবে আপনি কীভাবে জানবেন যে কোন পরিবর্তনটি প্রথমে ঘটে?
  2. যদি কোনও ভেরিয়েবল থাকে যা এক জায়গায় পরিবর্তিত হচ্ছে এবং এর মান অন্য জায়গায় ব্যবহার করা হচ্ছে তবে আপনি কীভাবে জানবেন যে এটি পুরানো মান ব্যবহার করে বা নতুন মানটি ব্যবহার করে?

অভিব্যক্তিতে # 1 এর উদাহরণ হিসাবে

x = x++ + ++x;

এক্স পরিবর্তন করতে তিনটি প্রচেষ্টা আছে।

অভিব্যক্তিতে # 2 এর উদাহরণ হিসাবে

y = x + x++;

আমরা উভয় এর মান ব্যবহার x এবং এটি সংশোধন করি।

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


3

কারণটি হ'ল প্রোগ্রামটি চলছে অপরিজ্ঞাত আচরণ। সমস্যাটি মূল্যায়নের আদেশের মধ্যে রয়েছে কারণ সি ++ 98 স্ট্যান্ডার্ড অনুসারে কোনও সিকোয়েন্স পয়েন্ট নেই (সি ++ 11 পরিভাষা অনুসারে কোনও ক্রিয়াকলাপের আগে বা পরে কোনও ক্রম হয় না)।

তবে আপনি যদি একটি সংকলককে আটকে থাকেন তবে আপনি আচরণটি অবিচলিত দেখতে পাবেন, যতক্ষণ আপনি ফাংশন কল বা পয়েন্টার যোগ করবেন না, যা আচরণকে আরও অগোছালো করে তুলবে।

  • সুতরাং প্রথমে জিসিসি: নুওয়েন মিনজিডাব্লু 15 জিসিসি 7.1 ব্যবহার করে আপনি পাবেন:

    #include<stdio.h>
    int main(int argc, char ** argv)
    {
    int i = 0;
    i = i++ + ++i;
    printf("%d\n", i); // 2
    
    i = 1;
    i = (i++);
    printf("%d\n", i); //1
    
    volatile int u = 0;
    u = u++ + ++u;
    printf("%d\n", u); // 2
    
    u = 1;
    u = (u++);
    printf("%d\n", u); //1
    
    register int v = 0;
    v = v++ + ++v;
    printf("%d\n", v); //2

    }

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

জিসিসি সি ++ অনুসারে : অপারেটর

জিসিসি সি ++ এ অপারেটরগুলির নজিরটি পৃথক অপারেটরদের মূল্যায়ন করার ক্রমটি নিয়ন্ত্রণ করে

সংজ্ঞায়িত আচরণের সমতুল্য কোড সি ++ জিসিসি যেমন বুঝতে পারে:

#include<stdio.h>
int main(int argc, char ** argv)
{
    int i = 0;
    //i = i++ + ++i;
    int r;
    r=i;
    i++;
    ++i;
    r+=i;
    i=r;
    printf("%d\n", i); // 2

    i = 1;
    //i = (i++);
    r=i;
    i++;
    i=r;
    printf("%d\n", i); // 1

    volatile int u = 0;
    //u = u++ + ++u;
    r=u;
    u++;
    ++u;
    r+=u;
    u=r;
    printf("%d\n", u); // 2

    u = 1;
    //u = (u++);
    r=u;
    u++;
    u=r;
    printf("%d\n", u); // 1

    register int v = 0;
    //v = v++ + ++v;
    r=v;
    v++;
    ++v;
    r+=v;
    v=r;
    printf("%d\n", v); //2
}

তারপরে আমরা ভিজ্যুয়াল স্টুডিওতে যাই । ভিজ্যুয়াল স্টুডিও 2015, আপনি পাবেন:

#include<stdio.h>
int main(int argc, char ** argv)
{
    int i = 0;
    i = i++ + ++i;
    printf("%d\n", i); // 3

    i = 1;
    i = (i++);
    printf("%d\n", i); // 2 

    volatile int u = 0;
    u = u++ + ++u;
    printf("%d\n", u); // 3

    u = 1;
    u = (u++);
    printf("%d\n", u); // 2 

    register int v = 0;
    v = v++ + ++v;
    printf("%d\n", v); // 3 
}

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

সুতরাং ভিজ্যুয়াল সি ++ যেমন বোঝে তেমন সংজ্ঞায়িত আচরণ সি ++ এর সমতুল্য:

#include<stdio.h>
int main(int argc, char ** argv)
{
    int r;
    int i = 0;
    //i = i++ + ++i;
    ++i;
    r = i + i;
    i = r;
    i++;
    printf("%d\n", i); // 3

    i = 1;
    //i = (i++);
    r = i;
    i = r;
    i++;
    printf("%d\n", i); // 2 

    volatile int u = 0;
    //u = u++ + ++u;
    ++u;
    r = u + u;
    u = r;
    u++;
    printf("%d\n", u); // 3

    u = 1;
    //u = (u++);
    r = u;
    u = r;
    u++;
    printf("%d\n", u); // 2 

    register int v = 0;
    //v = v++ + ++v;
    ++v;
    r = v + v;
    v = r;
    v++;
    printf("%d\n", v); // 3 
}

যেমন ভিজ্যুয়াল স্টুডিও ডকুমেন্টেশনটি মূল্যায়নের অগ্রাধিকার এবং আদেশে বলেছে :

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


1
ফাংশন আর্গুমেন্টগুলির মূল্যায়নে ইউবি যুক্ত করার জন্য আমি প্রশ্নটি সম্পাদনা করেছি, কারণ এই প্রশ্নটি প্রায়শই এর জন্য সদৃশ হিসাবে ব্যবহৃত হয়। (শেষ উদাহরণ)
অ্যান্টি হাপাল

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