I = (i, ++ i, 1) + 1 কী করে; না?


174

অপরিবর্তিত আচরণ এবং ক্রম পয়েন্টগুলি সম্পর্কে এই উত্তরটি পড়ার পরে , আমি একটি ছোট প্রোগ্রাম লিখেছিলাম:

#include <stdio.h>

int main(void) {
  int i = 5;
  i = (i, ++i, 1) + 1;
  printf("%d\n", i);
  return 0;
}

আউটপুট হয় 2। ওহ Godশ্বর, আমি হ্রাস আসতে দেখিনি! এখানে কি হচ্ছে?

উপরের কোডটি সংকলন করার সময়, আমি একটি সতর্কতা পেয়েছিলাম:

px.c: 5: 8: সতর্কতা: কমা প্রকাশের বাম-হাতের ক্রিয়াকলাপটির কোনও প্রভাব নেই

  [-Wunused-value]   i = (i, ++i, 1) + 1;
                        ^

কেন? তবে সম্ভবত এটি আমার প্রথম প্রশ্নের উত্তর দ্বারা স্বয়ংক্রিয়ভাবে উত্তর দেওয়া হবে।


289
অদ্ভুত জিনিস করবেন না, আপনার কোনও বন্ধু থাকবে না :(
মেরুন

9
সতর্কতা বার্তাটি আপনার প্রথম প্রশ্নের উত্তর।
ইউ হাও

2
@ সমারাম: না ফলে মান বাতিল করা হয়, পরিমার্জন না। আসল উত্তর: কমা অপারেটর একটি সিকোয়েন্স পয়েন্ট তৈরি করে।
করলি হরবাথ

3
@ গসমারস আপনার যখন 10 + টি প্রশ্নের সাথে ইতিবাচক স্কোর এবং তখন আরও বেশি কিছু থাকবে তখন আপনার যত্ন নেওয়া উচিত নয়।
মিথ্যা কথা বলছেনস্ক্রিয়

9
দ্রষ্টব্য: একটি অপ্টিমাইজ করা সংকলক সহজ কাজ করতে পারেprintf("2\n");
চুক্স - মোনিকা

উত্তর:


256

অভিব্যক্তিতে (i, ++i, 1), ব্যবহৃত কমাটি হ'ল কমা অপারেটর

কমা অপারেটর (টোকেন দ্বারা প্রতিনিধিত্ব করা ,) একটি বাইনারি অপারেটর যা তার প্রথম অপারেন্ডের মূল্যায়ন করে ফলাফলটি বাতিল করে দেয় এবং তারপরে দ্বিতীয় অপারেন্ডকে মূল্যায়ন করে এই মানটি (এবং টাইপ) প্রদান করে।

যেহেতু এটি তার প্রথম অপারেন্ডকে বাদ দেয়, এটি কেবল তখনই কার্যকর যখন প্রথম অপারেন্ডের পছন্দসই পার্শ্ব প্রতিক্রিয়া রয়েছে । যদি প্রথম অপারেন্ডে পার্শ্ব প্রতিক্রিয়া না ঘটে তবে সংকলকটি কোনও প্রভাব ছাড়াই অভিব্যক্তি সম্পর্কে সতর্কতা তৈরি করতে পারে।

সুতরাং, উপরের অভিব্যক্তিতে, বামতমটিকে iমূল্যায়ন করা হবে এবং এর মানটি বাতিল করা হবে। তারপরে ++iমূল্যায়ন করা হবে এবং i1 দ্বারা বৃদ্ধি হবে এবং আবার এক্সপ্রেশনটির মান ++iবাতিল হয়ে যাবে, তবে এর পার্শ্ব প্রতিক্রিয়া iস্থায়ী । তারপরে 1মূল্যায়ন করা হবে এবং প্রকাশের মান হবে 1

এটি সমান

i;          // Evaluate i and discard its value. This has no effect.
++i;        // Evaluate i and increment it by 1 and discard the value of expression ++i
i = 1 + 1;  

নোট করুন যে উপরের অভিব্যক্তিটি পুরোপুরি বৈধ এবং অনির্ধারিত আচরণকে সমর্থন করে না কারণ কমা অপারেটরের বাম এবং ডান ক্রিয়াকলাপগুলির মূল্যায়নের মধ্যে একটি সিকোয়েন্স পয়েন্ট রয়েছে।


1
যদিও চূড়ান্ত অভিব্যক্তিটি বৈধ, তবে দ্বিতীয় প্রকাশটি কি ++ আমি একটি পূর্বনির্ধারিত আচরণ নয়? এটি মূল্যায়ন করা হয় এবং অবিচ্ছিন্ন ভেরিয়েবলের মান প্রাক-বর্ধিত হয়, যা সঠিক নয়? নাকি আমি কিছু মিস করছি?
কুশিক শেঠি

2
@Koushik; iদিয়ে আরম্ভ করা হয় 5। ঘোষণা বিবৃতি দেখুন int i = 5;
হ্যাক

1
ওহ! আমার দুরবস্থা. দুঃখিত আমি সত্যিই তা দেখতে পাচ্ছি না।
কুশিক শেঠি

এখানে একটি ভুল রয়েছে: ++ আমি বৃদ্ধি করব আমি তার পরে মূল্যায়ন করব, যখন আমি ++ মূল্যায়ন করব আমি তারপরে এটি বৃদ্ধি করব।
কোয়ান্টিন হায়োট

1
@QuentinHayot; কি? কোনও পার্শ্ব প্রতিক্রিয়া প্রকাশের মূল্যায়নের পরে ঘটে। এর ক্ষেত্রে ++i, এই অভিব্যক্তিটি মূল্যায়ন করা iহবে , বর্ধিত হবে এবং এই বর্ধিত মানটি হবে অভিব্যক্তির মান। এর ক্ষেত্রে i++, এই অভিব্যক্তিটি মূল্যায়ন করা হবে, এর পুরাতন মানটি iপ্রকাশের মান iহবে , এক্সপ্রেশনটির পূর্ববর্তী এবং পরবর্তী ক্রমিক বিন্দুর মধ্যে যে কোনও সময়ে বর্ধিত হবে।
হ্যাক 16

62

C11অধ্যায় 6.5.17, কমা অপারেটর থেকে উদ্ধৃতি দেওয়া

কমা অপারেটরের বাম অপারেন্ডটি একটি শূন্য অভিব্যক্তি হিসাবে মূল্যায়ন করা হয়; এর মূল্যায়ন এবং সঠিক অপরেন্ডের মধ্যে একটি সিকোয়েন্স পয়েন্ট রয়েছে। তারপরে ডান অপরেন্ড মূল্যায়ন করা হয়; ফলাফলটির ধরণ এবং মান রয়েছে।

সুতরাং, আপনার ক্ষেত্রে,

(i, ++i, 1)

হিসাবে মূল্যায়ন করা হয়

  1. i, একটি অকার্যকর প্রকাশ হিসাবে মূল্যায়ন হয়, মূল্য বাতিল
  2. ++i, একটি অকার্যকর প্রকাশ হিসাবে মূল্যায়ন হয়, মূল্য বাতিল
  3. অবশেষে, 1মান ফিরে আসল।

সুতরাং, চূড়ান্ত বিবৃতি মত দেখাচ্ছে

i = 1 + 1;

এবং iপায় 2। আমি অনুমান করি এটি আপনার উভয় প্রশ্নের উত্তর দিয়েছে,

  • কীভাবে iমূল্য 2 হয়?
  • কেন একটি সতর্কতা বার্তা আছে?

দ্রষ্টব্য: এফডাব্লুআইডাব্লু, যেহেতু বাম হাতের অপারেন্ডের মূল্যায়নের পরে একটি সিকোয়েন্স পয়েন্ট উপস্থিত রয়েছে, যেমন একটি অভিব্যক্তি ইউবিকে (i, ++i, 1)ডাকে না, কারণ ভুল হিসাবে সাধারণত কেউ ভাবতে পারে


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

আমি কেন হ্যাকের উত্তর গ্রহণ করেছি তা আমাকে ব্যাখ্যা করতে হবে বলে আমি মনে করি। আমি আপনার গ্রহণ করতে প্রস্তুত ছিলাম যেহেতু এটি সত্যই আমার উভয় প্রশ্নের উত্তর দেয়। তবে, আপনি যদি আমার প্রশ্নের মন্তব্যগুলি পরীক্ষা করেন, আপনি দেখতে পাবেন যে কিছু লোক প্রথম নজরে দেখতে পাবে না কেন এটি ইউবিকে ডাকছে না। হ্যাকের উত্তরগুলি কিছু প্রাসঙ্গিক তথ্য সরবরাহ করে। অবশ্যই, আমার প্রশ্নে ইউবি সম্পর্কিত উত্তরটি আমার কাছে রয়েছে তবে কিছু লোক এটি মিস করতে পারে। আশা করি আপনি আমার বিবৃতিতে একমত, যদি আমাকে না জানায়। :)
gsamaras

30
i = (i, ++i, 1) + 1;

এর ধাপে ধাপে এটি বিশ্লেষণ করা যাক।

(i,   // is evaluated but ignored, there are other expressions after comma
++i,  // i is updated but the resulting value is ignored too
1)    // this value is finally used
+ 1   // 1 is added to the previous value 1

সুতরাং আমরা 2 প্রাপ্ত করি এবং এখনই চূড়ান্ত নিয়োগ:

i = 2;

এটি এখন ওভাররাইট করার আগে আমি যা ছিল তা ছিল ।


এটি বিবরণ দিয়ে সুন্দর হবে যে কমা অপারেটরের কারণে এটি ঘটে। ধাপে ধাপ বিশ্লেষণের জন্য যদিও +1! সুন্দর শীর্ষ উত্তর বিটিডব্লিউ।
gsamaras

অপর্যাপ্ত ব্যাখ্যার জন্য আমি দুঃখিত, আমার কাছে সেখানে কেবল একটি নোট রয়েছে ( ... তবে উপেক্ষা করা হচ্ছে, রয়েছে ... )। আমি মূলত ব্যাখ্যা করতে চেয়েছিলাম কেন ফলাফলটিতে ++iঅবদান রাখে না।
ডালস্ক

এখন আমার লুপগুলি সর্বদা সদৃশ হবেint i = 0; for( ;(++i, i<max); )
কফডি ডেভেলপার

19

এর ফলাফল

(i, ++i, 1)

হয়

1

জন্য

(i,++i,1) 

মূল্যায়ন এমন হয় যে ,অপারেটর মূল্যায়ন মূল্য বাতিল করে দেয় এবং ঠিক সঠিক মানটি ধরে রাখবে is1

সুতরাং

i = 1 + 1 = 2

1
হ্যাঁ আমিও সে কথা ভেবেছিলাম, তবে কেন জানি না!
gsamaras

@ গামারাস কারণ কমা অপারেটর পূর্ববর্তী শব্দটিকে মূল্যায়ন করে তবে তা ত্যাগ করে (অর্থাত্ এ্যাসাইনমেন্ট বা এর মতো ব্যবহার করে না)
মার্কো এ।

14

কমা অপারেটরের জন্য আপনি উইকি পৃষ্ঠায় কিছু ভাল পঠন পাবেন ।

মূলত, এটি

... এটির প্রথম অপারেন্ড মূল্যায়ন করে ফলাফলটি বাতিল করে, এবং তারপরে দ্বিতীয় অপারেন্ডকে মূল্যায়ন করে এই মানটি (এবং প্রকার) প্রদান করে।

এই যে মানে

(i, i++, 1)

পরিবর্তে, মূল্যায়ন i, ফলাফল বাতিল, ফলাফল মূল্যায়ন i++, ফলাফল বাতিল এবং তারপর মূল্যায়ন এবং ফিরে 1


হে ওহে জাহান্নাম, সিনট্যাক্সটি কি সি ++ তে বৈধ, আমার মনে আছে আমার এমন কয়েকটি জায়গা ছিল যেখানে আমার এই সিনট্যাক্সের প্রয়োজন ছিল (মূলত আমি লিখেছিলাম: (void)exp; a= exp2;যখন আমার কেবল দরকার ছিল a = exp, exp2;)
কোফডেপলপার

13

কমা অপারেটরটি এখানে কী করছে তা আপনার জানতে হবে:

আপনার অভিব্যক্তি:

(i, ++i, 1)

প্রথম এক্সপ্রেশন,, iমূল্যায়ন করা হয়, দ্বিতীয় প্রকাশটি, ++iমূল্যায়ন করা হয় এবং তৃতীয় এক্সপ্রেশন 1পুরো প্রকাশের জন্য ফিরে আসে returned

সুতরাং ফলাফল: i = 1 + 1

আপনার বোনাস প্রশ্নের জন্য, যেমন আপনি দেখেন, প্রথম প্রকাশটির iকোনও প্রভাব নেই, তাই সংকলকটি অভিযোগ করে।


5

কমাতে একটি 'বিপরীত' অগ্রাধিকার রয়েছে। এটি আপনি পুরানো বই এবং আইবিএম (70s / 80s) থেকে সি ম্যানুয়াল থেকে পাবেন। সুতরাং সর্বশেষ 'কমান্ড' হ'ল পিতামাতার অভিব্যক্তিতে ব্যবহৃত হয়।

আধুনিক সি তে এর ব্যবহারটি অদ্ভুত তবে পুরানো সি (এএনএসআই) এর মধ্যে খুব আকর্ষণীয়:

do { 
    /* bla bla bla, consider conditional flow with several continue's */
} while ( prepAnything(), doSomethingElse(), logic_operation);

সমস্ত ক্রিয়াকলাপ (ফাংশন) বাম থেকে ডানদিকে ডাকা হলেও শর্তসাপেক্ষে 'শেষ সময়' এর ফলে কেবল শেষ প্রকাশটি ব্যবহৃত হবে। এটি শর্ত যাচাইয়ের আগে চালানোর জন্য অনন্য কমান্ডের অনন্য ব্লক রাখার কাজটি পরিচালনা করতে বাধা দেয়।

সম্পাদনা: এটি হ্যান্ডলিং ফাংশনটিতে কল এড়াতে পারে যা বাম ক্রিয়াকলাপগুলিতে সমস্ত যুক্তির যত্ন নিতে পারে এবং তাই যৌক্তিক ফলাফলটি ফিরিয়ে দিতে পারে। মনে রাখবেন, সি এর অতীতে আমাদের ইনলাইন ফাংশন ছিল না তাই এটি একটি ওভারহেড কল এড়াতে পারে।


লুসিয়ানো, সেই জন্যই এই উত্তর এর প্রতি সংযোগ আছে পেয়েছেন: stackoverflow.com/questions/17902992/...
gsamaras

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