,
ऑपरेटर सी में क्या करता है?
,
ऑपरेटर सी में क्या करता है?
जवाबों:
भाव:
(expression1, expression2)
पहले एक्सप्रेशन 1 का मूल्यांकन किया जाता है, फिर एक्सप्रेशन 2 का मूल्यांकन किया जाता है, और एक्सप्रेशन 2 का मान पूरे एक्सप्रेशन के लिए वापस कर दिया जाता है।
i
पर 5, 4, 3, 2 या 1. मान नहीं होंगे । यह बस 0. है। यह व्यावहारिक रूप से बेकार है जब तक कि भावों पर दुष्प्रभाव न हो।
i = b, c;
के बराबर है, (i = b), c
क्योंकि असाइनमेंट =
में अल्पविराम ऑपरेटर की तुलना में अधिक पूर्वता है ,
। अल्पविराम ऑपरेटर की सबसे कम पूर्वता है।
expression1, expression2;
पहले expression1
मूल्यांकन किया जाता है, संभवतः इसके साइड-इफेक्ट्स के लिए (जैसे कि एक फ़ंक्शन को कॉल करना), फिर एक अनुक्रम बिंदु है, फिर expression2
मूल्यांकन किया जाता है और मान लौटाया जाता है ...
मैंने 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);
}
while (read_string(s) && s.len() > 5)
:। जाहिर है कि अगर read_string
रिटर्न वैल्यू नहीं है (या एक सार्थक नहीं है) काम नहीं करेगा। (संपादित करें: क्षमा करें, ध्यान नहीं दिया गया कि यह पद कितना पुराना है।)
while (1)
एक break;
बयान के साथ उपयोग करने से डरो मत । कोड के ब्रेक-आउट भाग को परीक्षण में या डाउन-टू-टेस्ट में लागू करने की कोशिश करना, अक्सर ऊर्जा की बर्बादी है और कोड को समझने में कठिन बनाता है।
while(1)
और से बेहतर है break
;
अल्पविराम ऑपरेटर बाईं संकार्य का मूल्यांकन करेंगे, परिणाम त्यागें और फिर सही संकार्य मूल्यांकन करें और उसे परिणाम होंगे। मुहावरेदार उपयोग लिंक में बताया गया है जब एक में इस्तेमाल किया चर आरंभ है 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) यदि कॉमा ऑपरेटर के परिणाम को संशोधित करने या अगले अनुक्रम बिंदु के बाद इसे एक्सेस करने का प्रयास किया जाता है, तो व्यवहार अनिर्धारित है।
फुटनोट 97 कहते हैं:
अल्पविराम ऑपरेटर लैवल्यू नहीं करता है ।
जिसका अर्थ है कि आप अल्पविराम ऑपरेटर के परिणाम को निर्दिष्ट नहीं कर सकते ।
यह ध्यान रखना महत्वपूर्ण है कि अल्पविराम ऑपरेटर में सबसे कम पूर्वता है और इसलिए ऐसे मामले हैं जहां उपयोग ()
करना एक बड़ा अंतर बना सकता है, उदाहरण के लिए:
#include <stdio.h>
int main()
{
int x, y ;
x = 1, 2 ;
y = (3,4) ;
printf( "%d %d\n", x, y ) ;
}
निम्नलिखित उत्पादन होगा:
1 4
अल्पविराम ऑपरेटर दोनों पक्षों को एक में जोड़ता है, दोनों का मूल्यांकन बाएं से दाएं क्रम में करता है। दाहिने हाथ की ओर का मूल्य पूरे अभिव्यक्ति के मूल्य के रूप में वापस किया जाता है।
(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 */
}
इसके अलावा, मैंने इसे केवल "क्रोध में" एक दूसरे मामले में उपयोग किया है, जब दो ऑपरेशनों को लपेटता है जो हमेशा एक मैक्रो में एक साथ जाना चाहिए। हमारे पास एक नेटवर्क पर भेजने के लिए बाइट बफर में विभिन्न बाइनरी मानों की नकल करने वाला कोड था, और एक पॉइंटर बनाए रखा गया था, जहां हम उठे थे:
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);
हालांकि, यह दृष्टिकोण सभी डेवलपर्स पर निर्भर करता था जो सभी वक्तव्यों में दोनों बयान डालते थे। हम एक ऐसा फंक्शन चाहते थे, जहां आप आउटपुट पॉइंटर, वैल्यू और वैल्यू टाइप में पास हो सकें। यह C, C ++ नहीं, टेम्प्लेट के साथ है, हम एक फंक्शन को मनमाना प्रकार नहीं ले सकते हैं, इसलिए हम एक मैक्रो पर बस गए:
#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
लाइन में अभिव्यक्तियों में केवल लूप-कंट्रोल कोड होना चाहिए, आरंभीकरण या लूप रखरखाव के अन्य अतिरिक्त बिट्स नहीं।
यह कई कथनों के मूल्यांकन का कारण बनता है, लेकिन परिणामी मूल्य (प्रतिद्वंद्विता, मुझे लगता है) के रूप में केवल पिछले एक का उपयोग करता है।
इसलिए...
int f() { return 7; }
int g() { return 8; }
int x = (printf("assigning x"), f(), g() );
x में परिणाम के लिए 8 सेट किया जाना चाहिए।
एकमात्र जगह जिसे मैंने देखा है वह उपयोगी है जब आप एक फंकी लूप लिखते हैं जहां आप एक भाव में कई चीजें करना चाहते हैं (शायद init एक्सप्रेशन या लूप एक्सप्रेशन। कुछ इस तरह:
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 और loop पर कई एक्सप्रेशन अधिक स्पष्ट होंगे। (और मैं घोषित करने के बजाय i1 और i2 इनलाइन को इनिशियलाइज़ करूँगा और फिर इनिशियलाइज़िंग करूँगा .... ब्ला ब्ला ब्ला)।
मैं इसे केवल @Rajesh और @JeffMercado से प्रश्नों को संबोधित करने के लिए पुनर्जीवित कर रहा हूं जो मुझे लगता है कि बहुत महत्वपूर्ण हैं क्योंकि यह शीर्ष खोज इंजन हिट में से एक है।
उदाहरण के लिए कोड का निम्नलिखित स्निपेट लें
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
। का परिणाम है(
अभिव्यक्ति ) is
1`।
j
मामला अलग पूर्वता नियमों का पालन करती बाद से ,
सबसे कम ऑपरेटर पूर्वता है। उन नियमों के कारण, संकलक असाइनमेंट-एक्सप्रेशन, स्थिर, स्थिर ... देखता है । अभिव्यक्तियों का फिर से बाएं-से-दाएं क्रम में मूल्यांकन किया जाता है और उनके दुष्प्रभाव दिखाई देते हैं, इसलिए,j
इसके 5
परिणामस्वरूप हैj = 5
।
अंतरराज्यीय रूप से, int j = 5,4,3,2,1;
भाषा की अनुमति नहीं है। एक आरंभिक एक असाइनमेंट-अभिव्यक्ति की उम्मीद करता है, इसलिए एक प्रत्यक्ष ,
ऑपरेटर की अनुमति नहीं है।
उम्मीद है की यह मदद करेगा।