खोज…


परिचय

एक प्रोग्रामिंग भाषा में एक ऑपरेटर एक प्रतीक है जो संकलक या दुभाषिया को एक विशिष्ट गणितीय, संबंधपरक या तार्किक संचालन करने और अंतिम परिणाम देने के लिए कहता है।

C में कई शक्तिशाली ऑपरेटर हैं। कई सी ऑपरेटर बाइनरी ऑपरेटर हैं, जिसका अर्थ है कि उनके पास दो ऑपरेंड हैं। उदाहरण के लिए, a / b , / में एक बाइनरी ऑपरेटर है जो दो ऑपरेंड ( a , b ) को स्वीकार करता है। कुछ एकरी संचालक हैं जो एक ऑपरेंड लेते हैं (उदाहरण के लिए: ~ , ++ ), और केवल एक टर्नरी ऑपरेटर ? :

वाक्य - विन्यास

  • expr1 ऑपरेटर
  • संचालक expr2
  • expr1 ऑपरेटर expr2
  • expr1? expr2: expr3

टिप्पणियों

ऑपरेटर्स एक arity, एक पूर्वता और एक संबद्धता है।

  • Arity ऑपरेंड की संख्या को इंगित करता है। सी में, तीन अलग-अलग ऑपरेटर की मौजूदगी होती है:

    • यूनिरी (1 ऑपरेंड)
    • बाइनरी (2 ऑपरेंड)
    • टर्नरी (3 ऑपरेंड)
  • वरीयता इंगित करती है कि कौन से ऑपरेटर अपने ऑपरेंड को पहले "बाइंड" करते हैं। अर्थात्, किस ऑपरेटर को अपने ऑपरेंड पर काम करने की प्राथमिकता है। उदाहरण के लिए, C भाषा उस अधिवेशन का पालन करती है जिसमें गुणा और भाग में जोड़ और घटाव की पूर्वता होती है:

    a * b + c
    

    के रूप में एक ही परिणाम देता है

    (a * b) + c
    

    यदि यह वह नहीं था जो कि चाहते थे, तो कोष्ठक का उपयोग करके पूर्वताप को मजबूर किया जा सकता है, क्योंकि उनके पास सभी ऑपरेटरों की सर्वोच्च मिसाल है।

    a * (b + c)
    

    यह नई अभिव्यक्ति एक परिणाम देगी जो पिछले दो अभिव्यक्तियों से अलग है।

    सी भाषा में कई पूर्वता स्तर हैं; पूर्वता के अवरोही क्रम में, सभी ऑपरेटरों के नीचे एक तालिका दी गई है।

    वरीयता तालिका

    ऑपरेटर्स संबद्धता
    () [] -> . बाएं से दाएं
    ! ~ ++ -- + - * (dereference) (type) sizeof दाएं से बाएं
    * (गुणा) / % बाएं से दाएं
    + - बाएं से दाएं
    << >> बाएं से दाएं
    < <= > >= बाएं से दाएं
    == != बाएं से दाएं
    & बाएं से दाएं
    ^ बाएं से दाएं
    | बाएं से दाएं
    && बाएं से दाएं
    || बाएं से दाएं
    ?: दाएं से बाएं
    = += -= *= /= %= &= ^= |= <<= >>= दाएं से बाएं
    , बाएं से दाएं
  • सहकारिता इंगित करती है कि कैसे समान-पूर्वता के ऑपरेटर डिफ़ॉल्ट रूप से बांधते हैं, और दो प्रकार हैं: लेफ्ट-टू-राइट और राइट-टू-लेफ्टबाएं से दाएं बंधन का एक उदाहरण घटाव ऑपरेटर ( - ) है। भाव

    a - b - c - d
    

    तीन समान-पूर्वता घटाव है, लेकिन जैसा है वैसा ही परिणाम देता है

    ((a - b) - c) - d
    

    क्योंकि बाएं-सबसे - अपने दो ऑपरेंड के लिए पहले बांधता है।

    राइट-टू-लेफ्ट एसोसिएटिविटी का एक उदाहरण डीरेफेरेंस * और पोस्ट-इंक्रीमेंट ++ ऑपरेटर्स हैं। दोनों में समान रूप से समानता है, इसलिए यदि उनका उपयोग अभिव्यक्ति में किया जाता है जैसे कि

    * ptr ++
    

    , इसके बराबर है

    * (ptr ++)
    

    क्योंकि सबसे सही, एकतरफा ऑपरेटर ( ++ ) सबसे पहले अपने सिंगल ऑपरेंड से बांधता है।

संबंधपरक संकारक

रिलेशनल ऑपरेटर्स चेक करते हैं कि दो ऑपरेंड्स के बीच एक विशिष्ट संबंध सही है या नहीं। परिणाम का मूल्यांकन 1 (जिसका अर्थ सत्य है ) या 0 (जिसका अर्थ असत्य ) है। इस परिणाम अक्सर (के माध्यम से नियंत्रण प्रवाह को प्रभावित करने के लिए प्रयोग किया जाता है if , while , for ), लेकिन यह भी चर में संग्रहित किया जा सकता है।

बराबर "=="

जाँच करता है कि आपूर्ति किए गए ऑपरेशंस समान हैं या नहीं।

1 == 0;         /* evaluates to 0. */
1 == 1;         /* evaluates to 1. */

int x = 5;
int y = 5;
int *xptr = &x, *yptr = &y;
xptr == yptr;   /* evaluates to 0, the operands hold different location addresses. */
*xptr == *yptr; /* evaluates to 1, the operands point at locations that hold the same value. */

ध्यान दें: इस ऑपरेटर को असाइनमेंट ऑपरेटर ( = ) के साथ भ्रमित नहीं होना चाहिए!

नहीं के बराबर "! ="

जाँच करता है कि आपूर्ति किए गए ऑपरेटर समान नहीं हैं।

1 != 0;         /* evaluates to 1. */
1 != 1;         /* evaluates to 0. */

int x = 5;
int y = 5;
int *xptr = &x, *yptr = &y;
xptr != yptr;   /* evaluates to 1, the operands hold different location addresses. */
*xptr != *yptr; /* evaluates to 0, the operands point at locations that hold the same value. */

यह ऑपरेटर बराबर ( == ) ऑपरेटर के विपरीत परिणाम को प्रभावी ढंग से वापस करता है।

नहीं "!"

जांचें कि कोई वस्तु 0 बराबर है या नहीं।

! निम्नानुसार एक चर के साथ सीधे इस्तेमाल किया जा सकता है:

!someVal

इसका एक ही प्रभाव है:

someVal == 0

">" से बड़ा

जाँचता है कि क्या बाएं हाथ के ऑपरेंड का दाएं हाथ के ऑपरेंड की तुलना में अधिक मूल्य है

5 > 4      /* evaluates to 1. */
4 > 5      /* evaluates to 0. */
4 > 4      /* evaluates to 0. */

"<" से कम

जाँचता है कि क्या बाएं हाथ के ऑपरेंड का दाएं हाथ के ऑपरेंड की तुलना में एक छोटा मूल्य है

5 < 4      /* evaluates to 0. */
4 < 5      /* evaluates to 1. */
4 < 4      /* evaluates to 0. */

से अधिक या बराबर "> ="

जाँच करता है कि बाएं हाथ के ऑपरेंड का सही ऑपरेंड के लिए अधिक या बराबर मूल्य है या नहीं।

5 >= 4      /* evaluates to 1. */
4 >= 5      /* evaluates to 0. */
4 >= 4      /* evaluates to 1. */

से कम या बराबर "<="

जाँच करता है कि बाएं हाथ के ऑपरेंड का दायां ऑपरेंड के लिए एक छोटा या समान मूल्य है या नहीं।

5 <= 4      /* evaluates to 0. */
4 <= 5      /* evaluates to 1. */
4 <= 4      /* evaluates to 1. */

असाइनमेंट ऑपरेटर्स

दाएँ हाथ के ऑपरेंड के मान को स्टोरेज लोकेशन पर लेफ्ट-हैंड ऑपरेंड द्वारा नामित मान देता है, और मान लौटाता है।

int x = 5;      /* Variable x holds the value 5. Returns 5. */ 
char y = 'c';   /* Variable y holds the value 99. Returns 99 
                 * (as the character 'c' is represented in the ASCII table with 99).
                 */
float z = 1.5;  /* variable z holds the value 1.5. Returns 1.5. */
char const* s = "foo"; /* Variable s holds the address of the first character of the string 'foo'. */

कई अंकगणितीय कार्यों में एक कंपाउंड असाइनमेंट ऑपरेटर होता है।

a += b  /* equal to: a = a + b */
a -= b  /* equal to: a = a - b */
a *= b  /* equal to: a = a * b */
a /= b  /* equal to: a = a / b */
a %= b  /* equal to: a = a % b */
a &= b  /* equal to: a = a & b */
a |= b  /* equal to: a = a | b */
a ^= b  /* equal to: a = a ^ b */
a <<= b /* equal to: a = a << b */
a >>= b /* equal to: a = a >> b */

इन यौगिक असाइनमेंट की एक महत्वपूर्ण विशेषता यह है कि बाएं हाथ की ओर ( a ) की अभिव्यक्ति केवल एक बार मूल्यांकन की जाती है। जैसे अगर p एक पॉइंटर है

*p += 27;

dereferences p केवल एक बार, जबकि निम्नलिखित दो बार ऐसा करता है।

*p = *p + 27;

यह भी ध्यान दिया जाना चाहिए कि एक असाइनमेंट का परिणाम जैसे कि a = b क्या है जिसे एक प्रतिद्वंद्विता के रूप में जाना जाता है। इस प्रकार, असाइनमेंट का वास्तव में एक मूल्य होता है जिसे बाद में दूसरे चर में सौंपा जा सकता है। यह एक ही कथन में कई चरों को सेट करने के लिए असाइनमेंट्स की चैनिंग करता है।

if कथन (या लूप या switch स्टेटमेंट) को नियंत्रित करने के भावों में इस शब्द का उपयोग किया जा सकता है जो किसी अन्य अभिव्यक्ति या फ़ंक्शन कॉल के परिणाम पर कुछ कोड की रक्षा करते हैं। उदाहरण के लिए:

char *buffer;
if ((buffer = malloc(1024)) != NULL)
{
    /* do something with buffer */
    free(buffer);
}
else
{
    /* report allocation failure */
}

इस वजह से, एक सामान्य टाइपो से बचने के लिए देखभाल की जानी चाहिए जिससे रहस्यमय कीड़े हो सकते हैं।

int a = 2;
/* ... */
if (a = 1)
    /* Delete all files on my hard drive */

इस विनाशकारी परिणाम के रूप में होगा, a = 1 हमेशा के लिए मूल्यांकन करेंगे 1 के इस प्रकार को नियंत्रित अभिव्यक्ति और if बयान हमेशा सच हो जाएगा (यह आम ख़तरा बारे में अधिक पढ़ने के लिए यहाँ )। लेखक लगभग निश्चित रूप से समानता ऑपरेटर ( == ) का उपयोग करने के लिए है जैसा कि नीचे दिखाया गया है:

int a = 2;
/* ... */
if (a == 1)
    /* Delete all files on my hard drive */

संचालक सहयोगी

int a, b = 1, c = 2;
a = b = c;

यह c से b को असाइन करता है, जो b लौटाता है, जो a को असाइन किया गया a । ऐसा इसलिए होता है क्योंकि सभी असाइनमेंट-ऑपरेटर्स में समरूपता होती है, अर्थात अभिव्यक्ति का सबसे सही संचालन पहले मूल्यांकन किया जाता है, और दाएं से बाएं ओर आगे बढ़ता है।

अंकगणितीय आपरेटर

मूल अंकगणित

एक मान लौटाएं जो संबंधित गणितीय कार्रवाई का उपयोग करके बाएं हाथ के ऑपरेंड को दाहिने हाथ के ऑपरेंड पर लागू करने का परिणाम है। कम्यूटेशन के सामान्य गणितीय नियम लागू होते हैं (यानी जोड़ और गुणा कम्यूटेटिव, घटाव, विभाजन और मापांक नहीं होते हैं)।

परिवर्धन संचालक

इसके अलावा ऑपरेटर ( + ) का उपयोग दो ऑपरेंड को एक साथ जोड़ने के लिए किया जाता है। उदाहरण:

#include <stdio.h>

int main(void)
{
    int a = 5;
    int b = 7;

    int c = a + b; /* c now holds the value 12 */

    printf("%d + %d = %d",a,b,c); /* will output "5 + 7 = 12" */

    return 0;
}

घटाव संचालक

घटाव ऑपरेटर ( - ) का उपयोग पहले से दूसरे ऑपरेंड को घटाने के लिए किया जाता है। उदाहरण:

#include <stdio.h>

int main(void)
{
    int a = 10;
    int b = 7;

    int c = a - b; /* c now holds the value 3 */

    printf("%d - %d = %d",a,b,c); /* will output "10 - 7 = 3" */

    return 0;
}

गुणक संचालक

गुणन ऑपरेटर ( * ) का उपयोग दोनों ऑपरेंड को गुणा करने के लिए किया जाता है। उदाहरण:

#include <stdio.h>

int main(void)
{    
    int a = 5;
    int b = 7;

    int c = a * b; /* c now holds the value 35 */

    printf("%d * %d = %d",a,b,c); /* will output "5 * 7 = 35" */

    return 0;
}

नहीं * उलझन ऑपरेटर के साथ भ्रमित होने की।

प्रभाग संचालक

डिवीजन ऑपरेटर ( / ) पहले ऑपरेंड को दूसरे द्वारा विभाजित करता है। यदि डिवीजन के दोनों ऑपरेंड पूर्णांक हैं, तो यह एक पूर्णांक मान लौटाएगा और शेष को छोड़ देगा (शेष की गणना और प्राप्त करने के लिए modulo ऑपरेटर % उपयोग करें)।

यदि ऑपरेंड में से एक फ्लोटिंग पॉइंट वैल्यू है, तो परिणाम अंश का एक अनुमान है।

उदाहरण:

#include <stdio.h>

int main (void)
{
    int a = 19 / 2 ; /* a holds value 9   */
    int b = 18 / 2 ; /* b holds value 9   */
    int c = 255 / 2; /* c holds value 127 */
    int d = 44 / 4 ; /* d holds value 11  */
    double e = 19 / 2.0 ; /* e holds value 9.5   */
    double f = 18.0 / 2 ; /* f holds value 9.0   */
    double g = 255 / 2.0; /* g holds value 127.5 */
    double h = 45.0 / 4 ; /* h holds value 11.25 */

    printf("19 / 2 = %d\n", a);    /* Will output "19 / 2 = 9"    */
    printf("18 / 2 = %d\n", b);    /* Will output "18 / 2 = 9"    */
    printf("255 / 2 = %d\n", c);   /* Will output "255 / 2 = 127" */
    printf("44 / 4 = %d\n", d);    /* Will output "44 / 4 = 11"   */
    printf("19 / 2.0 = %g\n", e);  /* Will output "19 / 2.0 = 9.5"    */
    printf("18.0 / 2 = %g\n", f);  /* Will output "18.0 / 2 = 9"      */
    printf("255 / 2.0 = %g\n", g); /* Will output "255 / 2.0 = 127.5" */
    printf("45.0 / 4 = %g\n", h);  /* Will output "45.0 / 4 = 11.25"  */

    return 0;
}

मोडुलो संचालक

मॉडुलो ऑपरेटर ( % ) केवल पूर्णांक ऑपरेंड प्राप्त करता है, और पहले ऑपरेंड को दूसरे द्वारा विभाजित किए जाने के बाद शेष की गणना करने के लिए उपयोग किया जाता है। उदाहरण:

#include <stdio.h>

int main (void) {
    int a = 25 % 2;    /* a holds value 1  */
    int b = 24 % 2;    /* b holds value 0  */
    int c = 155 % 5;   /* c holds value 0  */
    int d = 49 % 25;   /* d holds value 24 */

    printf("25 % 2 = %d\n", a);     /* Will output "25 % 2 = 1"    */
    printf("24 % 2 = %d\n", b);     /* Will output "24 % 2 = 0"    */
    printf("155 % 5 = %d\n", c);    /* Will output "155 % 5 = 0"   */
    printf("49 % 25 = %d\n", d);    /* Will output "49 % 25 = 24"  */

    return 0;
}

वेतन वृद्धि / कमी ऑपरेटर

वेतन वृद्धि ( a++ ) और डिक्रीमेंट ( a-- ) ऑपरेटर इस a-- में भिन्न होते हैं कि वे उस चर का मान बदलते हैं जो आप उन्हें बिना असाइनमेंट ऑपरेटर के लागू करते हैं। आप चर से पहले या बाद में वेतन वृद्धि और वेतन वृद्धि ऑपरेटरों का उपयोग कर सकते हैं। ऑपरेटर की नियुक्ति से पहले या इसके बाद वैरिएबल को असाइन करने के लिए मूल्य में वृद्धि / गिरावट का समय बदल जाता है। उदाहरण:

#include <stdio.h>

int main(void)
{
    int a = 1;
    int b = 4;
    int c = 1;
    int d = 4;

    a++;
    printf("a = %d\n",a);    /* Will output "a = 2" */
    b--;
    printf("b = %d\n",b);    /* Will output "b = 3" */

    if (++c > 1) { /* c is incremented by 1 before being compared in the condition */
        printf("This will print\n");    /* This is printed */
    } else {
        printf("This will never print\n");    /* This is not printed */
    }

    if (d-- < 4) {  /* d is decremented after being compared */
        printf("This will never print\n");    /* This is not printed */
    } else {
        printf("This will print\n");    /* This is printed */
    }
}

c और d शो के लिए उदाहरण के रूप में, दोनों ऑपरेटरों के दो रूप हैं, उपसर्ग संकेतन और उपसर्ग संकेतन। दोनों का एक ही प्रभाव है incrementing ( ++ ) या decrementing ( -- ) चर में, लेकिन उनके द्वारा लौटाए गए मान से भिन्न: उपसर्ग संचालन पहले ऑपरेशन करते हैं और फिर मान लौटाते हैं, जबकि पोस्टफ़िक्स ऑपरेशन पहले उस मान को निर्धारित करते हैं जो कि है लौटाया जाए, और फिर ऑपरेशन करें।

इस संभावित प्रति-सहज व्यवहार के कारण, भावों के अंदर वृद्धि / गिरावट संचालकों का उपयोग विवादास्पद है।

लॉजिकल ऑपरेटर्स

तार्किक और

यदि दोनों ऑपरेंड नॉन-जीरो हैं, तो 1 को वापस करने वाले दो ऑपरेंड्स का लॉजिकल बूलियन AND-ing करता है। लॉजिकल एंड ऑपरेटर टाइप int

0 && 0  /* Returns 0. */
0 && 1  /* Returns 0. */
2 && 0  /* Returns 0. */
2 && 3  /* Returns 1. */

तार्किक या

यदि कोई ऑपरेंड नॉन-जीरो है तो 1 लौटाने वाले दो ऑपरेंड्स का एक लॉजिकल बूलियन-आईएनजी करता है। तार्किक OR ऑपरेटर प्रकार int

0 || 0  /* Returns 0. */
0 || 1  /* Returns 1.  */
2 || 0  /* Returns 1.  */
2 || 3  /* Returns 1.  */

तार्किक नहीं

एक तार्किक निषेध करता है। तार्किक नहीं ऑपरेटर प्रकार int । यदि नहीं तो कम से कम एक बिट 1 के बराबर होने पर ऑपरेटर की जाँच नहीं करता है, यदि यह वापस आता है तो 0. यह 1 रिटर्न देता है;

!1 /* Returns 0. */
!5 /* Returns 0. */
!0 /* Returns 1. */

शॉर्ट-सर्किट मूल्यांकन

कुछ महत्वपूर्ण गुण हैं जो दोनों && और || :

  • बाएं हाथ के ऑपरेंड (LHS) का मूल्यांकन किया जाता है इससे पहले कि दाहिने हाथ के ऑपरेंड (RHS) का मूल्यांकन किया जाए,
  • बाएं हाथ के ऑपरेंड और राइट-हैंड ऑपरैंड के मूल्यांकन के बीच एक अनुक्रम बिंदु है,
  • और, सबसे महत्वपूर्ण बात, दाहिने हाथ के ऑपरेंड का बिल्कुल भी मूल्यांकन नहीं किया जाता है यदि बाएं हाथ के ऑपरेंड का परिणाम समग्र परिणाम निर्धारित करता है।

इस का मतलब है कि:

  • यदि LHS 'सत्य' (गैर-शून्य) का मूल्यांकन करता है, तो RHS || मूल्यांकन नहीं किया जाएगा (क्योंकि 'सत्य या कुछ भी' का परिणाम 'सत्य' है),
  • यदि LHS 'गलत' (शून्य) का मूल्यांकन करता है, तो && के RHS का मूल्यांकन नहीं किया जाएगा (क्योंकि 'गलत और कुछ भी' का परिणाम 'गलत' है)।

यह महत्वपूर्ण है क्योंकि यह आपको कोड लिखने की अनुमति देता है जैसे:

const char *name_for_value(int value)
{
    static const char *names[] = { "zero", "one", "two", "three", };
    enum { NUM_NAMES = sizeof(names) / sizeof(names[0]) };
    return (value >= 0 && value < NUM_NAMES) ? names[value] : "infinity";
}

यदि फ़ंक्शन को एक नकारात्मक मान दिया जाता है, तो value >= 0 शब्द गलत का मूल्यांकन करता है और value < NUM_NAMES शब्द का मूल्यांकन नहीं किया जाता है।

वेतन वृद्धि / कमी

वेतन वृद्धि और घटती ऑपरेटरों उपसर्ग और पोस्टफ़िक्स रूप में मौजूद हैं।

int a = 1;
int b = 1;
int tmp = 0;

tmp = ++a;        /* increments a by one, and returns new value; a == 2, tmp == 2  */
tmp = a++;        /* increments a by one, but returns old value; a == 3, tmp == 2 */
tmp = --b;        /* decrements b by one, and returns new value; b == 0, tmp == 0 */
tmp = b--;        /* decrements b by one, but returns old value; b == -1, tmp == 0 */

ध्यान दें कि अंकगणितीय संचालन अनुक्रम बिंदुओं को प्रस्तुत नहीं करते हैं, इसलिए ++ या -- ऑपरेटर्स के साथ कुछ अभिव्यक्तियाँ अपरिभाषित व्यवहार का परिचय दे सकती हैं

सशर्त संचालक / टर्नरी संचालक

इसके पहले ऑपरेंड का मूल्यांकन करता है, और यदि परिणामी मान शून्य के बराबर नहीं है, तो इसके दूसरे ऑपरेंड का मूल्यांकन करता है। अन्यथा, यह अपने तीसरे ऑपरेंड का मूल्यांकन करता है, जैसा कि निम्नलिखित उदाहरण में दिखाया गया है:

a = b ? c : d;

के बराबर है:

if (b)
    a = c;
else 
    a = d;

यह छद्म कोड इसका प्रतिनिधित्व करता है: condition ? value_if_true : value_if_false । प्रत्येक मान एक मूल्यांकित अभिव्यक्ति का परिणाम हो सकता है।

int x = 5;
int y = 42;
printf("%i, %i\n", 1 ? x : y, 0 ? x : y); /* Outputs "5, 42" */

सशर्त ऑपरेटर को नेस्टेड किया जा सकता है। उदाहरण के लिए, निम्नलिखित कोड तीन संख्याओं में से बड़ा निर्धारित करता है:

big= a > b ? (a > c ? a : c)
           : (b > c ? b : c);

निम्न उदाहरण एक फ़ाइल में पूर्णांक और दूसरी फ़ाइल में विषम पूर्णांक भी लिखते हैं:

#include<stdio.h>

int main()
{
    FILE *even, *odds;
    int n = 10;
    size_t k = 0;

    even = fopen("even.txt", "w");
    odds = fopen("odds.txt", "w");

    for(k = 1; k < n + 1; k++)
    {
        k%2==0 ? fprintf(even, "\t%5d\n", k)
               : fprintf(odds, "\t%5d\n", k);
    }
    fclose(even);
    fclose(odds);

    return 0;
}

सशर्त ऑपरेटर दाईं से बाईं ओर जुड़ता है। निम्नलिखित को धयान मे रखते हुए:

exp1 ? exp2 : exp3 ? exp4 : exp5

चूंकि एसोसिएशन दाएं से बाएं है, इसलिए उपरोक्त अभिव्यक्ति का मूल्यांकन किया जाता है

exp1 ? exp2 : ( exp3 ? exp4 : exp5 )

कोमा संचालक

इसके बाएं ऑपरेंड का मूल्यांकन करता है, जिसके परिणामस्वरूप मूल्य को छोड़ता है, और उसके बाद अपने अधिकार ऑपरेंड का मूल्यांकन करता है और परिणाम अपने सही ऑपरेंड के मूल्य को प्राप्त करता है।

int x = 42, y = 42;
printf("%i\n", (x *= 2, y)); /* Outputs "42". */

अल्पविराम ऑपरेटर अपने ऑपरेंड के बीच एक अनुक्रम बिंदु पेश करता है।

ध्यान दें कि फ़ंक्शंस में प्रयुक्त अल्पविराम कहता है कि अलग तर्क अल्पविराम ऑपरेटर नहीं है , बल्कि इसे एक विभाजक कहा जाता है जो अल्पविराम ऑपरेटर से अलग है। इसलिए, इसमें अल्पविराम ऑपरेटर के गुण नहीं हैं।

उपरोक्त printf() कॉल में कॉमा ऑपरेटर और विभाजक दोनों शामिल हैं।

printf("%i\n", (x *= 2, y)); /* Outputs "42". */
/*           ^        ^ this is a comma operator */
/*           this is a separator */

अल्पविराम ऑपरेटर का उपयोग अक्सर इनिशियलाइज़ेशन अनुभाग के साथ-साथ फ़ॉर लूप के अद्यतन अनुभाग में किया for है। उदाहरण के लिए:

for(k = 1; k < 10; printf("\%d\\n", k), k += 2);   /*outputs the odd numbers below 9/*

/* outputs sum to first 9 natural numbers */
for(sumk = 1, k = 1; k < 10; k++, sumk += k)
    printf("\%5d\%5d\\n", k, sumk);

कास्ट संचालक

दिए गए अभिव्यक्ति का मूल्यांकन करने के परिणामस्वरूप दिए गए मूल्य से दिए गए प्रकार में एक स्पष्ट रूपांतरण करता है।

int x = 3;
int y = 4;
printf("%f\n", (double)x / y); /* Outputs "0.750000". */

यहां x का मान एक double में बदल जाता है, विभाजन y के मूल्य को double करने के लिए double है, और विभाजन के परिणामस्वरूप, मुद्रण के लिए printf लिए एक double पास किया जाता है।

sizeof ऑपरेटर

एक प्रकार के साथ ऑपरेंड के रूप में

बाइट में आकार, प्रकार का मूल्यांकन करता है में size_t , यह देखते हुए प्रकार की वस्तुओं की। प्रकार के आसपास कोष्ठक की आवश्यकता होती है।

printf("%zu\n", sizeof(int)); /* Valid, outputs the size of an int object, which is platform-dependent. */
printf("%zu\n", sizeof int); /* Invalid, types as arguments need to be surrounded by parentheses! */

ओपेरा के रूप में एक अभिव्यक्ति के साथ

बाइट में आकार, प्रकार का मूल्यांकन करता है में size_t , यह देखते हुए अभिव्यक्ति के प्रकार की वस्तुओं की। स्वयं अभिव्यक्ति का मूल्यांकन नहीं किया जाता है। कोष्ठकों की आवश्यकता नहीं है; हालाँकि, क्योंकि दी गई अभिव्यक्ति एकरूप होनी चाहिए, यह हमेशा उनका उपयोग करने के लिए सबसे अच्छा अभ्यास माना जाता है।

char ch = 'a';
printf("%zu\n", sizeof(ch)); /* Valid, will output the size of a char object, which is always 1 for all platforms. */
printf("%zu\n", sizeof ch);  /* Valid, will output the size of a char object, which is always 1 for all platforms. */

सूचक अंकगणित

सूचक जोड़

एक पॉइंटर और एक स्केलर प्रकार N को देखते हुए, पॉइंट-टू टाइप के N वें तत्व के लिए एक पॉइंटर का मूल्यांकन करता है जो सीधे-सीधे ऑब्जेक्ट को मेमोरी में सफल करता है।

int arr[] = {1, 2, 3, 4, 5};
printf("*(arr + 3) = %i\n", *(arr + 3)); /* Outputs "4", arr's fourth element. */

इससे कोई फर्क नहीं पड़ता कि सूचक को ऑपरेंड मान या स्केलर मान के रूप में उपयोग किया जाता है। इसका मतलब है कि 3 + arr जैसी चीजें वैध हैं। यदि arr[k] है k+1 , एक सरणी के सदस्य तो arr+k के लिए सूचक है arr[k] । दूसरे शब्दों में, arr या arr+0 लिए एक संकेतक है arr[0] , arr+1 arr[2] और इसी तरह का एक सूचक है। सामान्य तौर पर, *(arr+k) arr[k]

सामान्य अंकगणितीय के विपरीत, एक सूचक से 1 int के अलावा वर्तमान पते के मूल्य में 4 बाइट जोड़ देगा। चूंकि सरणी नाम निरंतर पॉइंटर्स हैं, + एकमात्र ऑपरेटर है जिसका उपयोग हम सरणी नाम का उपयोग करके सूचक संकेतन के माध्यम से एक सरणी के सदस्यों तक पहुंचने के लिए कर सकते हैं। हालाँकि, एक पॉइंटर को एक व्यूअर में परिभाषित करके, हम एरे में डेटा को प्रोसेस करने के लिए अधिक लचीलापन प्राप्त कर सकते हैं। उदाहरण के लिए, हम एक सरणी के सदस्यों को निम्नानुसार प्रिंट कर सकते हैं:

#include<stdio.h>
static const size_t N = 5
    
int main()
{
    size_t k = 0;
    int arr[] = {1, 2, 3, 4, 5};
    for(k = 0; k < N; k++)
    {
        printf("\n\t%d", *(arr + k));
    }
    return 0;
}

सरणी के लिए एक सूचक को परिभाषित करके, उपरोक्त कार्यक्रम निम्न के बराबर है:

#include<stdio.h>
static const size_t N = 5
    
int main()
{
    size_t k = 0;
    int arr[] = {1, 2, 3, 4, 5};
    int *ptr = arr; /* or int *ptr = &arr[0]; */
    for(k = 0; k < N; k++)
    {
        printf("\n\t%d", ptr[k]);
        /* or   printf("\n\t%d", *(ptr + k)); */
        /* or   printf("\n\t%d", *ptr++); */
    }
    return 0;
}

देखें कि सरणी arr के सदस्य आपरेटरों + और ++ का उपयोग करके एक्सेस किए जाते हैं। अन्य ऑपरेटर जिन्हें पॉइंटर ptr साथ उपयोग किया जा सकता है वे हैं - और --

सूचक घटाव

एक ही प्रकार के दो ptrdiff_t को देखते हुए, उस प्रकार के ऑब्जेक्ट का मूल्यांकन करता है जो कि ptrdiff_t है जो स्केलर मान रखता है जिसे पहले पॉइंटर का मान प्राप्त करने के लिए दूसरे पॉइंटर में जोड़ा जाना चाहिए।

int arr[] = {1, 2, 3, 4, 5};
int *p = &arr[2];
int *q = &arr[3];
ptrdiff_t diff = q - p;

printf("q - p = %ti\n", diff); /* Outputs "1". */
printf("*(p + (q - p)) = %d\n", *(p + diff)); /* Outputs "4". */

पहुंच संचालक

सदस्य पहुंच ऑपरेटरों (डॉट . और तीर -> ) का उपयोग किसी struct सदस्य तक पहुंचने के लिए किया जाता है।

वस्तु का सदस्य

पहुँच योग्य वस्तु का एक सदस्य है जो वस्तु को दर्शाते हुए अंतराल में मूल्यांकन करता है।

struct MyStruct
{
    int x;
    int y;
};

struct MyStruct myObject;
myObject.x = 42;
myObject.y = 123;

printf(".x = %i, .y = %i\n", myObject.x, myObject.y); /* Outputs ".x = 42, .y = 123". */

इंगित करने वाली वस्तु का सदस्य

सदस्य अभिगमन के बाद डेरेफ्रेंसिंग के लिए सिंथेटिक शुगर। प्रभावी रूप से, प्रपत्र x->y की एक अभिव्यक्ति है (*x).y लिए शॉर्टहैंड - लेकिन एरो ऑपरेटर बहुत स्पष्ट है, खासकर अगर संरचना के संकेत नेस्टेड हैं।

struct MyStruct
{
    int x;
    int y;
};

struct MyStruct myObject;
struct MyStruct *p = &myObject;

p->x = 42;
p->y = 123;

printf(".x = %i, .y = %i\n", p->x, p->y); /* Outputs ".x = 42, .y = 123". */
printf(".x = %i, .y = %i\n", myObject.x, myObject.y); /* Also outputs ".x = 42, .y = 123". */

का पता

अपर & ऑपरेटर ऑपरेटर का पता है। यह दी गई अभिव्यक्ति का मूल्यांकन करता है, जहां परिणामी वस्तु को एक अंतराल होना चाहिए। फिर, यह एक ऐसी वस्तु का मूल्यांकन करता है जिसका प्रकार परिणामी वस्तु के प्रकार का सूचक होता है, और परिणामी वस्तु का पता होता है।

int x = 3;
int *p = &x;
printf("%p = %p\n", (void *)&x, (void *)p); /* Outputs "A = A", for some implementation-defined A. */

भिन्नता

यूनीरी * ऑपरेटर एक पॉइंटर को डीरफेर करता है। यह दिए गए अभिव्यक्ति का मूल्यांकन करने वाले पॉइंटर को डेरेफेरिंग से उत्पन्न अंतराल में मूल्यांकन करता है।

int x = 42;
int *p = &x;
printf("x = %d, *p = %d\n", x, *p); /* Outputs "x = 42, *p = 42". */

*p = 123;
printf("x = %d, *p = %d\n", x, *p); /* Outputs "x = 123, *p = 123". */

इंडेक्सिंग

इंडेक्सिंग शुगर के लिए सूचक जोड़ के साथ अनुक्रमित चीनी है जिसके बाद डेरेफेरिंग होती है। प्रभावी रूप से, a[i] फॉर्म की एक अभिव्यक्ति *(a + i) बराबर है - लेकिन स्पष्ट सबस्क्रिप्ट नोटेशन को प्राथमिकता दी जाती है।

int arr[] = { 1, 2, 3, 4, 5 };
printf("arr[2] = %i\n", arr[2]); /* Outputs "arr[2] = 3". */

अनुक्रमण की विनिमेयता

किसी पूर्णांक में एक सूचक जोड़ना एक कम्यूटेटिव ऑपरेशन होता है (यानी ऑपरेंड का क्रम परिणाम नहीं बदलता है) इसलिए pointer + integer == integer + pointer

इसका एक परिणाम यह है कि arr[3] और 3[arr] बराबर है।

printf("3[arr] = %i\n", 3[arr]); /* Outputs "3[arr] = 4". */

एक अभिव्यक्ति का उपयोग 3[arr] के बजाय arr[3] आम तौर पर की सिफारिश नहीं है, यह कोड पठनीयता को प्रभावित करता है के रूप में किया जाता है। यह ओफ़्फ़ुसेटेड प्रोग्रामिंग प्रतियोगिता में एक लोकप्रिय होना है।

फंक्शन कॉल ऑपरेटर

पहला ऑपरेंड एक फ़ंक्शन पॉइंटर होना चाहिए (एक फ़ंक्शन डिज़ाइनर भी स्वीकार्य है क्योंकि यह फ़ंक्शन के लिए एक पॉइंटर में परिवर्तित हो जाएगा), फ़ंक्शन को कॉल करने के लिए पहचानता है, और अन्य सभी ऑपरेंड, यदि कोई हो, सामूहिक रूप से फ़ंक्शन कॉल के तर्क के रूप में जाना जाता है। । संबंधित तर्कों के साथ उपयुक्त फ़ंक्शन को कॉल करने के परिणामस्वरूप वापसी मान का मूल्यांकन करता है।

int myFunction(int x, int y)
{
    return x * 2 + y;
}

int (*fn)(int, int) = &myFunction;
int x = 42;
int y = 123;

printf("(*fn)(%i, %i) = %i\n", x, y, (*fn)(x, y)); /* Outputs "fn(42, 123) = 207". */
printf("fn(%i, %i) = %i\n", x, y, fn(x, y)); /* Another form: you don't need to dereference explicitly */

बिटवाइज ऑपरेटर्स

बिटवाइज ऑपरेटर्स का इस्तेमाल वेरिएबल्स पर बिट लेवल ऑपरेशन करने के लिए किया जा सकता है।
नीचे C में समर्थित सभी छह बिटवाइज़ ऑपरेटरों की सूची दी गई है:

प्रतीक ऑपरेटर
और बिटवाइंड एंड
| बिटवाइस समावेशी या
^ बिटवाइज़ एक्सक्लूसिव OR (XOR)
~ बिटवाइज़ नहीं (किसी का पूरक)
<< तार्किक बाईं पारी
>> तार्किक सही बदलाव

निम्नलिखित कार्यक्रम सभी बिटवाइज़ ऑपरेटरों के उपयोग को दर्शाता है:

#include <stdio.h>

int main(void)
{
   unsigned int a = 29;    /* 29 = 0001 1101 */  
   unsigned int b = 48;    /* 48 = 0011 0000 */
   int c = 0;           

   c = a & b;              /* 32 = 0001 0000 */ 
   printf("%d & %d = %d\n", a, b, c );

   c = a | b;              /* 61 = 0011 1101 */
   printf("%d | %d = %d\n", a, b, c );

   c = a ^ b;              /* 45 = 0010 1101 */
   printf("%d ^ %d = %d\n", a, b, c );

   c = ~a;                 /* -30 = 1110 0010 */
   printf("~%d = %d\n", a, c );

   c = a << 2;             /* 116 = 0111 0100 */
   printf("%d << 2 = %d\n", a, c );

   c = a >> 2;             /* 7 = 0000 0111 */
   printf("%d >> 2 = %d\n", a, c );

   return 0;
}

हस्ताक्षरित प्रकारों के साथ बिटवाइज़ संचालन से बचना चाहिए क्योंकि इस तरह के बिट प्रतिनिधित्व के संकेत बिट का एक विशेष अर्थ है। शिफ्ट ऑपरेटरों पर विशेष रूप से प्रतिबंध लागू होते हैं:

  • हस्ताक्षर किए गए बिट में 1 बिट को शिफ्ट करना गलत है और अपरिभाषित व्यवहार की ओर ले जाता है।

  • ऋणात्मक मान को स्थानांतरित करना (साइन बिट 1 के साथ) कार्यान्वयन परिभाषित है और इसलिए पोर्टेबल नहीं है।

  • यदि शिफ्ट ऑपरेटर के दाहिने ऑपरेंड का मान नकारात्मक है या पदोन्नत किए गए बाएं ऑपरेंड की चौड़ाई के बराबर या उससे अधिक है, तो व्यवहार अपरिभाषित है।

मास्किंग:

मास्किंग तार्किक बिटवाइज़ संचालन का उपयोग करके एक चर से वांछित बिट्स को निकालने (या वांछित बिट्स को बदलने) की प्रक्रिया को संदर्भित करता है। जिस ऑपरेंड (एक स्थिर या परिवर्तनशील) का उपयोग मास्किंग करने के लिए किया जाता है उसे मास्क कहा जाता है।

मास्किंग का उपयोग कई अलग-अलग तरीकों से किया जाता है:

  • पूर्णांक चर के बिट पैटर्न को तय करने के लिए।
  • किसी दिए गए बिट पैटर्न के एक हिस्से को एक नए चर में कॉपी करने के लिए, जबकि नए चर के शेष भाग को 0s (बिटवाइड और) का उपयोग करके भरा जाता है।
  • किसी दिए गए बिट पैटर्न के एक हिस्से को एक नए चर में कॉपी करने के लिए, जबकि नए चर के शेष भाग को 1s (बिटवाइज़ या का उपयोग करके) से भरा जाता है।
  • किसी दिए गए बिट पैटर्न के एक हिस्से को एक नए चर में कॉपी करने के लिए, जबकि मूल बिट पैटर्न के शेष को नए चर (बिटवाइड एक्सक्लूसिव OR का उपयोग करके) के भीतर उलटा किया जाता है।

निम्न फ़ंक्शन एक चर के बिट पैटर्न को प्रदर्शित करने के लिए एक मुखौटा का उपयोग करता है:

#include <limits.h>
void bit_pattern(int u)
{
    int i, x, word;
    unsigned mask = 1;
    word = CHAR_BIT * sizeof(int);
    mask = mask << (word - 1);    /* shift 1 to the leftmost position */
    for(i = 1; i <= word; i++)
    {
        x = (u & mask) ? 1 : 0;  /* identify the bit */
        printf("%d", x);         /* print bit value */
        mask >>= 1;              /* shift mask to the right by 1 bit */
    }
}

_Alignof

C11

निर्दिष्ट प्रकार के लिए संरेखण आवश्यकता को क्वेरी करता है। संरेखण की आवश्यकता 2 की एक सकारात्मक अभिन्न शक्ति है जो बाइट्स की संख्या का प्रतिनिधित्व करती है जिसके बीच प्रकार की दो वस्तुओं को आवंटित किया जा सकता है। सी में, संरेखण आवश्यकता को size_t में मापा जाता है।

प्रकार नाम अधूरा प्रकार और फ़ंक्शन प्रकार नहीं हो सकता है। यदि किसी सरणी का उपयोग प्रकार के रूप में किया जाता है, तो सरणी तत्व का उपयोग किया जाता है।

इस ऑपरेटर को अक्सर <stdalign.h> से मैक्रो alignof की सुविधा के माध्यम से एक्सेस किया जाता है।

int main(void)
{
    printf("Alignment of char = %zu\n", alignof(char));
    printf("Alignment of max_align_t = %zu\n", alignof(max_align_t));
    printf("alignof(float[10]) = %zu\n", alignof(float[10]));
    printf("alignof(struct{char c; int n;}) = %zu\n",
            alignof(struct {char c; int n;}));    
}

संभावित आउटपुट:

Alignment of char = 1
Alignment of max_align_t = 16
alignof(float[10]) = 4
alignof(struct{char c; int n;}) = 4

http://en.cppreference.com/w/c/language/_Alignof

तार्किक ऑपरेटरों के शॉर्ट सर्किट व्यवहार

शॉर्ट सर्किटिंग एक ऐसी कार्यक्षमता है जो सक्षम होने पर (यदि / / / ...) स्थिति के कुछ हिस्सों का मूल्यांकन करती है। दो ऑपरेंड पर एक तार्किक ऑपरेशन के मामले में, पहले ऑपरेंड का मूल्यांकन (सही या गलत के लिए) किया जाता है और यदि कोई निर्णय (यानी पहला ऑपरेंड गलत होता है जब & quot; का उपयोग करते समय पहला ऑपरेंड सही होता है) || दूसरा ऑपरेंड || मूल्यांकित नहीं।

उदाहरण:

#include <stdio.h>
 
int main(void) {
  int a = 20;
  int b = -5;
 
  /* here 'b == -5' is not evaluated,
     since a 'a != 20' is false. */
  if (a != 20 && b == -5) {
    printf("I won't be printed!\n");
  }
   
  return 0;
}

इसे स्वयं देखें:

#include <stdio.h>
 
int print(int i) {
  printf("print function %d\n", i);
  return i;
}
 
int main(void) {
  int a = 20;
 
  /* here 'print(a)' is not called,
     since a 'a != 20' is false. */
  if (a != 20 && print(a)) {
    printf("I won't be printed!\n");
  }

  /* here 'print(a)' is called,
     since a 'a == 20' is true. */
  if (a == 20 && print(a)) {
    printf("I will be printed!\n");
  }

  return 0;
}

आउटपुट:

$ ./a.out
print function 20
I will be printed!

शॉर्ट सर्कुलेटिंग महत्वपूर्ण है, जब आप उन शब्दों के मूल्यांकन से बचना चाहते हैं जो (कम्प्यूटेशनल रूप से) महंगे हैं। इसके अलावा, यह इस तरह से आपके कार्यक्रम के प्रवाह को बहुत प्रभावित कर सकता है: यह कार्यक्रम "कांटा लगा" क्यों छापता है! 4 बार?



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow