কমা অপারেটর কি করে?


167

,অপারেটর সি তে কি করে ?



1
আমি আমার উত্তরে নোট হিসাবে বাম অপারেন্ড মূল্যায়নের পরে একটি ক্রম পয়েন্ট আছে। এটি কোনও ফাংশন কলের কমা বিপরীতে যা কেবল ব্যাকরণগত।
শফিক ইয়াঘমোর

2
@SergeyK। - এটির জিজ্ঞাসা করা হয়েছিল এবং উত্তর দেওয়ার আগে কয়েক বছর আগে, এটি সম্ভবত এই প্রশ্নটির সদৃশ অন্যটি। তবে অন্যটি সি এবং সি ++ উভয়ের সাথেও দ্বৈত ট্যাগযুক্ত যা একটি উপদ্রব। এটি একটি সি-কেবল প্রশ্নোত্তর, যার উত্তম উত্তর রয়েছে।
জোনাথন লেফলার

উত্তর:


129

অভিব্যক্তি:

(expression1,  expression2)

প্রথম এক্সপ্রেশন 1 মূল্যায়ন করা হয়, তারপরে এক্সপ্রেশন 2 মূল্যায়ন করা হয়, এবং এক্সপ্রেশন 2 এর মান পুরো এক্সপ্রেশনটির জন্য ফিরে আসে।


3
তারপরে আমি যদি i = (5,4,3,2,1,0) লিখি তবে আদর্শভাবে এটি 0, সঠিক হওয়া উচিত? কিন্তু আমি 5 এর মূল্য নির্ধারণ করা হচ্ছে? আপনি দয়া করে আমাকে বুঝতে সাহায্য করতে পারেন আমি কোথায় ভুল করছি?
জয়েশ

19
@ জেমস: কমা অপারেশনের মান সর্বদা সর্বশেষ অভিব্যক্তিটির মান হবে। কোনও বিন্দুতে i5, 4, 3, 2 বা 1 এর মান থাকবে না এটি কেবল 0 is
জেফ মার্কাডো

6
নোট কমা মত প্রকাশের LHS মূল্যায়ন ও RHS মূল্যায়ন মধ্যে একটি পূর্ণ ক্রম বিন্দু নেই (দেখুন শফিক Yaghmour এর উত্তর C99 মান থেকে উদ্ধৃতি জন্য)। এটি কমা অপারেটরের একটি গুরুত্বপূর্ণ সম্পত্তি।
জোনাথন লেফলার

5
i = b, c;সমতুল্য (i = b), cকারণ অ্যাসাইনমেন্ট =কমা অপারেটরের চেয়ে উচ্চতর প্রাধান্য আছে ,। কমা অপারেটরের সবার চেয়ে কম অগ্রাধিকার রয়েছে।
চক্রবিজ্ঞানী

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

119

আমি whileলুপগুলিতে সর্বাধিক ব্যবহৃত দেখেছি :

string s;
while(read_string(s), s.len() > 5)
{
   //do something
}

এটি অপারেশনটি করবে, তারপরে পার্শ্ব-প্রতিক্রিয়াটির ভিত্তিতে একটি পরীক্ষা করবে। অন্য উপায়টি এটির মতো করে করা হবে:

string s;
read_string(s);
while(s.len() > 5)
{
   //do something
   read_string(s);
}

21
এই যে নিফটি! এই সমস্যাটি সমাধান করার জন্য আমাকে প্রায়শই লম্পটে অপ্রচলিত কাজ করতে হয়েছিল।
স্ট্যাটিকসান

6
যদিও এটা সম্ভবত কম অস্পষ্ট এবং আরো পাঠযোগ্য হতে চাই যদি আপনি চান কিছু করেছিল: while (read_string(s) && s.len() > 5)। স্পষ্টতই read_stringএটির কার্যকর হবে না যদি কোনও রিটার্ন মান না থাকে (বা অর্থপূর্ণ কোনও না থাকে)। (সম্পাদনা করুন: দুঃখিত, পোস্টটি কতটা পুরানো তা লক্ষ্য করেননি))
জেমসডলিন ২৮'১০

11
@ স্ট্যাটিক্সন শরীরে while (1)একটি break;বিবৃতি ব্যবহার করতে ভয় পাবেন না । কোডটির ব্রেক-আউট অংশটি পরীক্ষার সময় বা ডাউন-টেস্টের মধ্যে চাপিয়ে দেওয়ার চেষ্টা করা প্রায়শই শক্তির অপচয় এবং কোডটি বোঝা আরও শক্ত করে তোলে।
potrzebie

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

3
@ পোত্রজেবি আমি কমা পদ্ধতির চেয়ে অনেক বেশি পছন্দ করি while(1)এবং break;
মাইকেল

38

কমা অপারেটর বাম প্রতীক মূল্যায়ন করবে, ফলে বাতিল তারপর ডানদিকের প্রতীক মূল্যায়ন এবং যে ফল কী হবে। কথ্য ব্যবহার লিঙ্কে উল্লিখিত একটি ব্যবহৃত ভেরিয়েবল শুরু হচ্ছে forলুপ, এবং এটি নিম্নলিখিত উদাহরণে দেয়:

void rev(char *s, size_t len)
{
  char *first;
  for ( first = s, s += len - 1; s >= first; --s)
      /*^^^^^^^^^^^^^^^^^^^^^^^*/ 
      putchar(*s);
}

অন্যথায় কমা অপারেটরের অনেক দুর্দান্ত ব্যবহার নেই , যদিও পড়তে ও বজায় রাখা শক্ত এমন কোড উত্পন্ন করার জন্য এটি অপব্যবহার করা সহজ।

থেকে খসড়া C99 মান ব্যাকরণ নিম্নরূপ:

expression:
  assignment-expression
  expression , assignment-expression

এবং অনুচ্ছেদ 2 বলেছেন:

একটি কমা অপারেটর বাঁদিকে প্রতীক একটি অকার্যকর অভিব্যক্তি হিসাবে মূল্যায়ন করা হয়; এর মূল্যায়নের পরে একটি সিকোয়েন্স পয়েন্ট রয়েছে। তারপরে ডান অপরেন্ড মূল্যায়ন করা হয়; ফলাফলটির ধরণ এবং মান রয়েছে। ৯)) যদি কমা অপারেটরের ফলাফলটি পরিবর্তন করতে বা পরবর্তী সিকোয়েন্স পয়েন্টের পরে এটি অ্যাক্সেস করার চেষ্টা করা হয়, তবে আচরণটি সংজ্ঞায়িত।

পাদটীকা 97 বলেছেন:

কমা অপারেটর একটি লভ্যালু দেয় না

যার অর্থ আপনি কমা অপারেটরের ফলাফলকে বরাদ্দ করতে পারবেন না ।

এটি লক্ষ করা গুরুত্বপূর্ণ যে কমা অপারেটরের সর্বনিম্ন প্রাধান্য রয়েছে এবং তাই এমন কিছু ক্ষেত্রে রয়েছে যেখানে ব্যবহার করা ()একটি বড় পার্থক্য করতে পারে, উদাহরণস্বরূপ:

#include <stdio.h>

int main()
{
    int x, y ;

    x = 1, 2 ;
    y = (3,4) ;

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

নিম্নলিখিত আউটপুট হবে:

1 4

28

কমা অপারেটর উভয় এক্সপ্রেশনকে এর উভয় পাশকে এক সাথে সংযুক্ত করে, উভয়কে বাম থেকে ডানে ক্রমে মূল্যায়ন করে। ডান-হাতের মানটি পুরো এক্সপ্রেশনটির মান হিসাবে ফিরে আসে। (expr1, expr2)মত { expr1; expr2; }তবে আপনি expr2একটি ফাংশন কল বা অ্যাসাইনমেন্টের ফলাফল ব্যবহার করতে পারেন ।

এটিকে forএকাধিক ভেরিয়েবল শুরু করতে বা বজায় রাখতে প্রায়শই লুপগুলিতে দেখা যায় :

for (low = 0, high = MAXSIZE; low < high; low = newlow, high = newhigh)
{
    /* do something with low and high and put new values
       in newlow and newhigh */
}

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

unsigned char outbuff[BUFFSIZE];
unsigned char *ptr = outbuff;

*ptr++ = first_byte_value;
*ptr++ = second_byte_value;

send_buff(outbuff, (int)(ptr - outbuff));

যেখানে মানগুলি shortবা intগুলি ছিল আমরা এটি করেছি:

*((short *)ptr)++ = short_value;
*((int *)ptr)++ = int_value;

পরে আমরা পড়লাম যে এটি সত্যিকার অর্থে বৈধ সি ছিল না, কারণ (short *)ptrএখন আর এল-মান হয় না এবং বাড়ানো যায় না, যদিও আমাদের সংকলকটি তখন আপত্তি করত না। এটি ঠিক করার জন্য, আমরা এক্সপ্রেশনটিকে দুটি ভাগে ভাগ করি:

*(short *)ptr = short_value;
ptr += sizeof(short);

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

#define ASSIGN_INCR(p, val, type)  ((*((type) *)(p) = (val)), (p) += sizeof(type))

কমা অপারেটরটি ব্যবহার করে আমরা এটি প্রকাশ করতে বা আমাদের ইচ্ছামতো বিবৃতি হিসাবে ব্যবহার করতে সক্ষম হয়েছি:

if (need_to_output_short)
    ASSIGN_INCR(ptr, short_value, short);

latest_pos = ASSIGN_INCR(ptr, int_value, int);

send_buff(outbuff, (int)(ASSIGN_INCR(ptr, last_value, int) - outbuff));

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


ধন্যবাদ! এটি স্ট্যাকওভারফ্লোতে আমার প্রথম উত্তর ছিল: তখন থেকে আমি সম্ভবত শিখেছি যে সংক্ষিপ্ততার মূল্য দেওয়া উচিত :-)।
পল স্টিফেনসন

কখনও কখনও আমি কিছুটা ভারবোসিটির মূল্য হিসাবে বিবেচনা করি যেখানে আপনি এখানে সমাধানের বিবর্তন বর্ণনা করেছেন (আপনি সেখানে কীভাবে এসেছেন)।
সবুজ ডায়োড

8

এটি একাধিক বিবৃতিগুলির মূল্যায়নের কারণ ঘটায়, তবে ফলস্বরূপ মান হিসাবে কেবল শেষটি ব্যবহার করে (মূল্যায়ন, আমি মনে করি)।

তাই ...

int f() { return 7; }
int g() { return 8; }

int x = (printf("assigning x"), f(), g() );

x 8 এ সেট হওয়ার ফলাফল হওয়া উচিত।


3

পূর্বের উত্তরগুলি বলেছে যে এটি সমস্ত বিবৃতি মূল্যায়ন করে তবে শেষটিরটিকে অভিব্যক্তির মান হিসাবে ব্যবহার করে। ব্যক্তিগতভাবে আমি এটি কেবল লুপ এক্সপ্রেশনগুলিতে দরকারী পেয়েছি:

for (tmp=0, i = MAX; i > 0; i--)

2

আমি এটি কার্যকর হতে দেখেছি কেবলমাত্র সেই জায়গাটি যখন আপনি কোনও মজাদার লুপটি লিখেন যেখানে আপনি কোনও একটি এক্সপ্রেশনে একাধিক জিনিস করতে চান (সম্ভবত থিম এক্সপ্রেশন বা লুপ এক্সপ্রেশন like

bool arraysAreMirrored(int a1[], int a2[], size_t size)
{
  size_t i1, i2;
  for(i1 = 0, i2 = size - 1; i1 < size; i1++, i2--)
  {
    if(a1[i1] != a2[i2])
    {
      return false;
    }
  }

  return true;
}

ক্ষমা করুন যদি কোনও বাক্য গঠন ত্রুটি থাকে বা আমি এমন কোনও কিছু মিশ্রিত করি যা কঠোর নয় সি। আমি যুক্তি দিচ্ছি না যে, অপারেটরটি ভাল ফর্ম, তবে আপনি এটির জন্য এটি ব্যবহার করতে পারেন। উপরের ক্ষেত্রে আমি সম্ভবত whileপরিবর্তে একটি লুপ ব্যবহার করব যাতে init এবং লুপের একাধিক অভিব্যক্তি আরও স্পষ্ট হয়। (এবং আমি ঘোষণার পরিবর্তে i1 এবং i2 ইনলাইনটি শুরু করতে এবং তারপরে আরম্ভ করার চেষ্টা করব .... ব্লাহ ব্লাহ ব্লাহ।)


আমি অনুমান করি আপনার অর্থ i1 = 0, i2 = আকার -1
ফ্রাঙ্কস্টার

-2

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

উদাহরণস্বরূপ নীচের কোডের স্নিপেট নিন

int i = (5,4,3,2,1);
int j;
j = 5,4,3,2,1;
printf("%d %d\n", i , j);

এটি মুদ্রণ করবে

1 5

iঅধিকাংশ উত্তর দ্বারা ব্যাখ্যা ক্ষেত্রে পরিচালিত হয়। সমস্ত এক্সপ্রেশন বাম থেকে ডান ক্রমে মূল্যায়ন করা হয় তবে কেবল সর্বশেষটি নির্ধারিত হয় i( প্রকাশের ফলাফল ) 1 ) is

jকেস বিভিন্ন প্রাধান্য নিয়ম অনুসরণ করে যেহেতু ,সর্বনিম্ন অপারেটর প্রাধান্য আছে। কারণ সেই নিয়ম, কম্পাইলার দেখেন ... কার্যভার অভিব্যক্তি, ধ্রুবক, ধ্রুবক । এক্সপ্রেশন আবার বাম-থেকে-ডান ক্রম এবং তাদের পার্শ্ব প্রতিক্রিয়া দৃশ্যমান থাকার ফলে মূল্যায়ন করা হয় jহয় 5ফলে j = 5

আন্তঃআদ্দীপকভাবে, int j = 5,4,3,2,1;ভাষা অনুমান দ্বারা অনুমোদিত নয়। একটি প্রাথমিককরণ কোনও অ্যাসাইনমেন্ট-এক্সপ্রেশন আশা করে যাতে সরাসরি ,অপারেটরের অনুমতি দেওয়া হয় না।

আশাকরি এটা সাহায্য করবে.

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