खोज…


टिप्पणियों

ऑब्जेक्ट या फ़ंक्शन का उल्लेख करने वाले पहचानकर्ता की घोषणा को अक्सर ऑब्जेक्ट या फ़ंक्शन की घोषणा के रूप में संक्षेप में संदर्भित किया जाता है।

किसी अन्य C फ़ाइल से फ़ंक्शन कॉल करना

foo.h

#ifndef FOO_DOT_H    /* This is an "include guard" */
#define FOO_DOT_H    /* prevents the file from being included twice. */
                     /* Including a header file twice causes all kinds */
                     /* of interesting problems.*/

/**
 * This is a function declaration.
 * It tells the compiler that the function exists somewhere.
 */
void foo(int id, char *name);

#endif /* FOO_DOT_H */

foo.c

#include "foo.h"    /* Always include the header file that declares something
                     * in the C file that defines it. This makes sure that the
                     * declaration and definition are always in-sync.  Put this
                     * header first in foo.c to ensure the header is self-contained.
                     */
#include <stdio.h>
                       
/**
 * This is the function definition.
 * It is the actual body of the function which was declared elsewhere.
 */
void foo(int id, char *name)
{
    fprintf(stderr, "foo(%d, \"%s\");\n", id, name);
    /* This will print how foo was called to stderr - standard error.
     * e.g., foo(42, "Hi!") will print `foo(42, "Hi!")`
     */
}

main.c

#include "foo.h"

int main(void)
{
    foo(42, "bar");
    return 0;
}

संकलन और लिंक

सबसे पहले, हम ऑब्जेक्ट फ़ाइलों के लिए foo.c और main.c दोनों को संकलित करते हैं। यहां हम gcc संकलक का उपयोग करते हैं, आपके संकलक का एक अलग नाम हो सकता है और अन्य विकल्पों की आवश्यकता हो सकती है।

$ gcc -Wall -c foo.c
$ gcc -Wall -c main.c

अब हम उन्हें अपने अंतिम निष्पादन योग्य बनाने के लिए एक साथ जोड़ते हैं:

$ gcc -o testprogram foo.o main.o

एक वैश्विक चर का उपयोग करना

वैश्विक चर का उपयोग आमतौर पर हतोत्साहित किया जाता है। यह आपके कार्यक्रम को समझने में अधिक कठिन है, और डीबग करना कठिन है। लेकिन कभी-कभी एक वैश्विक चर का उपयोग करना स्वीकार्य होता है।

global.h

#ifndef GLOBAL_DOT_H    /* This is an "include guard" */
#define GLOBAL_DOT_H

/**
 * This tells the compiler that g_myglobal exists somewhere.
 * Without "extern", this would create a new variable named
 * g_myglobal in _every file_ that included it. Don't miss this!
 */
extern int g_myglobal; /* _Declare_ g_myglobal, that is promise it will be _defined_ by
                        * some module. */

#endif /* GLOBAL_DOT_H */

global.c

#include "global.h" /* Always include the header file that declares something
                     * in the C file that defines it. This makes sure that the
                     * declaration and definition are always in-sync.
                     */
                       
int g_myglobal;     /* _Define_ my_global. As living in global scope it gets initialised to 0 
                     * on program start-up. */

main.c

#include "global.h"

int main(void)
{
    g_myglobal = 42;
    return 0;
}

यह भी देखें कि स्रोत फ़ाइलों के बीच चर साझा करने के लिए मैं extern उपयोग कैसे करूं?

वैश्विक स्थिरांक का उपयोग करना

उदाहरण के लिए स्ट्रिंग टेबल की तरह विश्व स्तर पर उपयोग किए जाने वाले केवल संसाधनों को घोषित करने के लिए हेडर का उपयोग किया जा सकता है।

एक अलग हेडर में उन लोगों को घोषित करें जो किसी भी फ़ाइल (" ट्रांसलेशन यूनिट ") द्वारा शामिल हो जाते हैं जो उनका उपयोग करना चाहता है। सभी स्ट्रिंग-संसाधनों की पहचान करने के लिए संबंधित एन्यूमरेशन घोषित करने के लिए एक ही हेडर का उपयोग करना आसान है:

resources.h:

#ifndef RESOURCES_H
#define RESOURCES_H

typedef enum { /* Define a type describing the possible valid resource IDs. */
  RESOURCE_UNDEFINED = -1, /* To be used to initialise any EnumResourceID typed variable to be 
                              marked as "not in use", "not in list", "undefined", wtf.
                              Will say un-initialised on application level, not on language level. Initialised uninitialised, so to say ;-)
                              Its like NULL for pointers ;-)*/
  RESOURCE_UNKNOWN = 0,    /* To be used if the application uses some resource ID, 
                              for which we do not have a table entry defined, a fall back in 
                              case we _need_ to display something, but do not find anything 
                              appropriate. */

  /* The following identify the resources we have defined: */
  RESOURCE_OK,
  RESOURCE_CANCEL,
  RESOURCE_ABORT,
  /* Insert more here. */

  RESOURCE_MAX /* The maximum number of resources defined. */
} EnumResourceID;


extern const char * const resources[RESOURCE_MAX]; /* Declare, promise to anybody who includes 
                                      this, that at linkage-time this symbol will be around. 
                                      The 1st const guarantees the strings will not change, 
                                      the 2nd const guarantees the string-table entries 
                                      will never suddenly point somewhere else as set during 
                                      initialisation. */
#endif

वास्तव में संबंधित .c-file बनाने वाले संसाधनों को परिभाषित करने के लिए, संबंधित हेडर (.h) फ़ाइल में घोषित किए गए वास्तविक उदाहरणों को रखने वाली एक अन्य अनुवाद इकाई है:

resources.c:

#include "resources.h" /* To make sure clashes between declaration and definition are
                          recognised by the compiler include the declaring header into
                          the implementing, defining translation unit (.c file).

/* Define the resources. Keep the promise made in resources.h. */
const char * const resources[RESOURCE_MAX] = {
  "<unknown>",
  "OK",
  "Cancel",
  "Abort"
};

इसका उपयोग करने वाला एक कार्यक्रम इस तरह दिख सकता है:

main.c:

#include <stdlib.h> /* for EXIT_SUCCESS */
#include <stdio.h>

#include "resources.h"


int main(void)
{
  EnumResourceID resource_id = RESOURCE_UNDEFINED;

  while ((++resource_id) < RESOURCE_MAX)
  {
    printf("resource ID: %d, resource: '%s'\n", resource_id, resources[resource_id]);
  }

  return EXIT_SUCCESS;
}

GCC का उपयोग करके ऊपर की तीन फ़ाइल संकलित करें, और उदाहरण के लिए प्रोग्राम फ़ाइल main बनने के लिए उन्हें लिंक करें:

gcc -Wall -Wextra -pedantic -Wconversion -g  main.c resources.c -o main

(इन का उपयोग करें -Wall -Wextra -pedantic -Wconversion बनाने के लिए संकलक वास्तव में picky, तो आप एसओ को कोड पोस्ट करने से पहले कुछ भी याद नहीं करते हैं, दुनिया कहेंगे, या यहां तक कि इसे उत्पादन में तैनात करने के लायक है)

बनाया गया कार्यक्रम चलाएं:

$ ./main

और पाओ:

resource ID: 0, resource: '<unknown>'
resource ID: 1, resource: 'OK'
resource ID: 2, resource: 'Cancel'
resource ID: 3, resource: 'Abort'

परिचय

घोषणाओं के उदाहरण हैं:

int a; /* declaring single identifier of type int */

ऊपर घोषणा नामित एकल पहचानकर्ता वाणी a है जिसके साथ किसी वस्तु को संदर्भित करता है int प्रकार।

int a1, b1; /* declaring 2 identifiers of type int */

दूसरी घोषणा में a1 b1 और b1 नाम के 2 पहचानकर्ताओं की घोषणा की गई है जो समान int प्रकार के साथ कुछ अन्य वस्तुओं को संदर्भित करता है।

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

/* 1 */ int /* 2 */ (*z) /* 3 */ , /* 4 */ *x , /* 5 */ **c /* 6 */ ;
# विवरण
1 पूर्णांक प्रकार का नाम।
2 कुछ पहचानकर्ता z लिए अप्रत्यक्ष रूप से आवेदन करने वाली असंबद्ध अभिव्यक्ति।
3 हमारे पास एक अल्पविराम है जो दर्शाता है कि एक और अभिव्यक्ति एक ही घोषणा में अनुसरण करेगी।
4 कुछ अन्य पहचानकर्ता x लिए अप्रत्यक्ष रूप से आवेदन करने वाली असंबद्ध अभिव्यक्ति।
5 अभिव्यक्ति के मूल्य (*c) लिए अप्रत्यक्ष रूप से लागू करने वाली अभिव्यक्ति का मूल्यांकन।
6 घोषणा का अंत।

ध्यान दें कि इस घोषणा से पहले उपरोक्त कोई भी पहचानकर्ता दिखाई नहीं दे रहा था और इसलिए इस्तेमाल किए गए भाव इसके पहले मान्य नहीं होंगे।

ऐसी प्रत्येक अभिव्यक्ति के बाद, इसमें प्रयुक्त पहचानकर्ता को वर्तमान दायरे में पेश किया जाता है। (यदि पहचानकर्ता ने इसे लिंकेज सौंपा है, तो इसे उसी प्रकार के लिंकेज के साथ फिर से घोषित किया जा सकता है, ताकि दोनों पहचानकर्ता एक ही वस्तु या फ़ंक्शन को देखें)

इसके अतिरिक्त, प्रारंभ के लिए समान ऑपरेटर चिह्न ( = ) का उपयोग किया जा सकता है। अगर घोषणा के अंदर एक अनवैल्युएटेड एक्सप्रेशन (घोषणाकर्ता) = बाद होता है - हम कहते हैं कि जो पहचानकर्ता पेश किया जा रहा है, वह भी आरंभीकृत है। = चिन्ह के बाद हम एक बार फिर से कुछ अभिव्यक्ति कर सकते हैं, लेकिन इस बार इसका मूल्यांकन किया जाएगा और इसके मूल्य को घोषित वस्तु के लिए प्रारंभिक रूप में उपयोग किया जाएगा।

उदाहरण:

int l = 90; /* the same as: */

int l; l = 90; /* if it the declaration of l was in block scope */

int c = 2, b[c]; /* ok, equivalent to: */

int c = 2; int b[c];

आपके कोड में बाद में, आपको नए शुरू किए गए पहचानकर्ता के घोषणा भाग से सटीक एक ही अभिव्यक्ति लिखने की अनुमति है, आपको घोषणा की शुरुआत में निर्दिष्ट प्रकार की एक वस्तु दे रही है, यह मानते हुए कि आपने सभी एक्सेस किए गए मान्य मान असाइन किए हैं रास्ते में वस्तुएँ। उदाहरण:

void f()
{
    int b2; /* you should be able to write later in your code b2 
            which will directly refer to the integer object
            that b2 identifies */
    
    b2 = 2; /* assign a value to b2 */
    
    printf("%d", b2); /*ok - should print 2*/

    int *b3; /* you should be able to write later in your code *b3 */

    b3 = &b2; /* assign valid pointer value to b3 */

    printf("%d", *b3); /* ok - should print 2 */

    int **b4; /* you should be able to write later in your code **b4 */

    b4 = &b3;

    printf("%d", **b4); /* ok - should print 2 */

    void (*p)(); /* you should be able to write later in your code (*p)() */

    p = &f; /* assign a valid pointer value */

    (*p)(); /* ok - calls function f by retrieving the
            pointer value inside p -    p
            and dereferencing it -      *p
            resulting in a function
            which is then called -      (*p)() -

            it is not *p() because else first the () operator is 
            applied to p and then the resulting void object is
            dereferenced which is not what we want here */
}

b3 3 की घोषणा निर्दिष्ट करती है कि आप कुछ पूर्णांक वस्तु तक पहुंचने के लिए एक b3 रूप में संभावित रूप से b3 मूल्य का उपयोग कर सकते हैं।

बेशक, b3 लिए अप्रत्यक्ष ( * ) लागू करने के लिए, आपके पास इसमें एक उचित मूल्य भी होना चाहिए (अधिक जानकारी के लिए संकेत देखें)। इसे पुनर्प्राप्त करने का प्रयास करने से पहले आपको पहले कुछ मूल्य को एक वस्तु में संग्रहित करना चाहिए (आप यहां इस समस्या के बारे में अधिक देख सकते हैं)। हमने उपरोक्त उदाहरणों में यह सब किया है।

int a3(); /* you should be able to call a3 */

यह एक कंपाइलर को बताता है कि आप a3 को कॉल करने का प्रयास करेंगे। इस मामले में a3 एक वस्तु के बजाय कार्य को संदर्भित करता है। ऑब्जेक्ट और फ़ंक्शन के बीच एक अंतर यह है कि फ़ंक्शन में हमेशा कुछ प्रकार के लिंकेज होंगे। उदाहरण:

void f1()
{
    {
        int f2(); /* 1 refers to some function f2 */
    }
    
    {
        int f2(); /* refers to the exact same function f2 as (1) */
    }
}

उपरोक्त उदाहरण में, 2 घोषणाएं समान फ़ंक्शन f2 को संदर्भित करती हैं, जबकि यदि वे वस्तुओं की घोषणा कर रहे थे तो इस संदर्भ में (2 अलग-अलग ब्लॉक स्कोप) होने पर, उनके पास 2 अलग-अलग ऑब्जेक्ट होंगे।

int (*a3)(); /* you should be able to apply indirection to `a3` and then call it */

अब यह जटिल प्रतीत हो सकता है, लेकिन यदि आप ऑपरेटरों को पूर्वता से जानते हैं तो आपको उपरोक्त घोषणा को पढ़ने में 0 समस्याएं होंगी। कोष्ठक की आवश्यकता है क्योंकि * ऑपरेटर की पूर्ववर्तीता कम है ( ) तब ( ) एक।

सबस्क्रिप्ट ऑपरेटर का उपयोग करने के मामले में, परिणामी अभिव्यक्ति वास्तव में घोषणा के बाद मान्य नहीं होगी क्योंकि इसमें प्रयुक्त सूचकांक ( [ और ] अंदर का मूल्य) इस ऑब्जेक्ट / फ़ंक्शन के लिए अधिकतम अनुमत मूल्य से हमेशा 1 ऊपर होगा।

int a4[5]; /* here a4 shouldn't be accessed using the index 5 later on */

लेकिन यह सभी अन्य अनुक्रमित कम तब तक सुलभ होना चाहिए। 5. उदाहरण:

a4[0], a4[1]; a4[4];

a4[5] का परिणाम UB होगा। सरणियों के बारे में अधिक जानकारी यहां पाई जा सकती है

int (*a5)[5](); /* here a4 could be applied indirection
                indexed up to (but not including) 5
                and called */

दुर्भाग्यवश, हमारे लिए, हालांकि वाक्यात्मक रूप से संभव है, a5 की घोषणा वर्तमान मानक द्वारा निषिद्ध है।

typedef

टंकण वे घोषणाएँ हैं जिनके सामने और प्रकार से पहले खोजशब्द typedef है। उदाहरण के लिए:

typedef int (*(*t0)())[5];

( आप टाइप करने के बाद भी तकनीकी रूप से टाइपफेड डाल सकते हैं - जैसे यह int typedef (*(*t0)())[5]; लेकिन यह हतोत्साहित करता है )

उपर्युक्त घोषणाएं एक टाइपराइफ नाम के लिए एक पहचानकर्ता की घोषणा करती हैं। आप इसे इस तरह बाद में उपयोग कर सकते हैं:

t0 pf;

जो लेखन के रूप में एक ही प्रभाव होगा:

int (*(*pf)())[5];

जैसा कि आप देख सकते हैं कि टाइप्डिफ नाम "घोषणा" को अन्य घोषणाओं के लिए बाद में उपयोग करने के लिए एक प्रकार के रूप में सहेजता है। इस तरह आप कुछ कीस्ट्रोक्स बचा सकते हैं। इसके अलावा typedef का उपयोग करते हुए घोषणा अभी भी एक घोषणा है जिसे आप केवल उपरोक्त उदाहरण द्वारा सीमित नहीं हैं:

t0 (*pf1);

के समान है:

int (*(**pf1)())[5];

C घोषणा को समझने के लिए दाएं-बाएं या सर्पिल नियम का उपयोग करना

"राइट-लेफ्ट" नियम सी घोषणाओं को डिक्रिप्ट करने के लिए एक पूरी तरह से नियमित नियम है। यह उन्हें बनाने में भी उपयोगी हो सकता है।

घोषणा में उनका सामना करने के रूप में प्रतीकों को पढ़ें ...

*   as "pointer to"          - always on the left side
[]  as "array of"            - always on the right side
()  as "function returning"  - always on the right side

नियम कैसे लागू करें

चरण 1

पहचानकर्ता का पता लगाएं। यह आपका शुरुआती बिंदु है। फिर खुद से कहें, "पहचानकर्ता है।" आपने अपनी घोषणा शुरू कर दी है।

चरण 2

पहचानकर्ता के दाईं ओर प्रतीकों को देखें। यदि, कहते हैं, तो आप पाते हैं () , तो आप जानते हैं कि यह एक समारोह के लिए घोषणा है। तो आपके पास "पहचानकर्ता फ़ंक्शन वापस लौट रहा है" होगा । या अगर आपको वहां एक [] मिला, तो आप कहेंगे "पहचानकर्ता सरणी है" । जब तक आप प्रतीकों से बाहर नहीं निकलते या दाएं कोष्ठक से टकराते हैं ) सही जारी रखें। (यदि आप एक बाएं कोष्ठक से टकराते हैं ( , यह एक () प्रतीक की शुरुआत है, भले ही कोष्ठक के बीच में सामान हो। नीचे उस पर और अधिक।)

चरण 3

पहचानकर्ता के बाईं ओर प्रतीकों को देखें। यदि यह ऊपर हमारे प्रतीकों में से एक नहीं है (कहो, "इंट" जैसा कुछ), तो बस कहें। अन्यथा, उपरोक्त तालिका का उपयोग करके इसे अंग्रेजी में अनुवाद करें। जब तक आप प्रतीकों से बाहर नहीं निकलते हैं या एक बाएं कोष्ठक से टकराते रहते हैं (

अब चरण 2 और 3 को तब तक दोहराएं जब तक आप अपनी घोषणा नहीं कर लेते।


यहाँ कुछ उदाहरण हैं:

int *p[];

सबसे पहले, पहचानकर्ता खोजें:

int *p[];
     ^

"पी है"

अब, जब तक प्रतीकों या सही कोष्ठक हिट से बाहर न जाएं, तब तक दाईं ओर ले जाएं।

int *p[];
      ^^

"पी सरणी है"

अब और आगे नहीं जा सकते (प्रतीकों में से), इसलिए बाएं चलें और खोजें:

int *p[];
    ^

"p पॉइंटर ऑफ़ पॉइंटर" है

बाएं चलते रहें और खोजें:

int *p[];
^^^

"पी int के लिए सूचक की सरणी है"।

(या "p एक सरणी है जहाँ प्रत्येक तत्व int के लिए पॉइंटर पॉइंटर का है" )

एक और उदाहरण:

int *(*func())();

पहचानकर्ता का पता लगाएं।

int *(*func())();
       ^^^^

"फंक है"

दाएँ चले।

int *(*func())();
           ^^

"फंक फंक्शन रिटर्निंग"

दाएं कोष्ठक के कारण अब और नहीं चल सकते, इसलिए बाएं जाएं।

int *(*func())();
      ^

"func फंक्शन रिटर्न पॉइंटर है"

बाएं कोष्ठक के कारण अब बाएं नहीं जा सकते, इसलिए दाएं चलते रहें।

int *(*func())();
              ^^

"फंक फंक्शन पॉइंटर रिटर्निंग टू फंक्शन रिटर्निंग है"

हम प्रतीकों से बाहर होने के कारण अब आगे नहीं बढ़ सकते, इसलिए बाईं ओर जाएं।

int *(*func())();
    ^

"फंक फंक्शन पॉइंटर रिटर्निंग फंक्शन है जो रिटर्निंग पॉइंटर"

और अंत में, बाएं चलते रहें, क्योंकि दाईं ओर कुछ भी नहीं बचा है।

int *(*func())();
^^^

"फंक कार्य पॉइंटर रिटर्न करने के लिए फ़ंक्शन पॉइंटर इंट करने के लिए कार्य करता है"।

जैसा कि आप देख सकते हैं, यह नियम काफी उपयोगी हो सकता है। आप घोषणाओं का निर्माण करते समय स्वयं की जांच करने के लिए इसका उपयोग कर सकते हैं, और आपको यह संकेत देने के लिए कि अगला प्रतीक कहां रखा जाए और क्या कोष्ठक की आवश्यकता है।

कुछ घोषणाएँ आकार में सरणी आकार और तर्क सूचियों के कारण अधिक जटिल दिखती हैं। यदि आप [3] देखते हैं, तो इसे "सरणी (आकार 3) ..." के रूप में पढ़ा जाता है। यदि आप देखते हैं (char *,int) जो कि * "फ़ंक्शन की उम्मीद (चार , int) और लौट रहे हैं ..." के रूप में पढ़ा जाता है।

यहाँ एक मजेदार है:

int (*(*fun_one)(char *,double))[9][20];

मैं इसे समझने के लिए प्रत्येक चरण से नहीं गुज़रूंगा।

* "fun_one, सूचक (चार , डबल) और पॉइंटर को सरणी (आकार 9) के सरणी (आकार 20) की ओर लौटने के लिए सूचक है।"

जैसा कि आप देख सकते हैं, यह उतना जटिल नहीं है अगर आपको सरणी के आकार और तर्क सूचियों से छुटकारा मिल जाए:

int (*(*fun_one)())[][];

आप इसे इस तरह से व्याख्या कर सकते हैं, और फिर बाद में सरणी आकार और तर्क सूची में डाल सकते हैं।

कुछ अंतिम शब्द:


इस नियम का उपयोग करके अवैध घोषणाएं करना काफी संभव है, इसलिए सी में कानूनी क्या है, इसका कुछ ज्ञान आवश्यक है। उदाहरण के लिए, यदि ऊपर दिया गया है:

int *((*fun_one)())[][];

यह पढ़ा होगा "fun_one पॉइंटर टू पॉइंट ऑफ़ पॉइंट ऑफ़ पॉइंट टू इंट टू फंक्शन" है । चूंकि कोई फ़ंक्शन किसी सरणी को नहीं लौटा सकता है, लेकिन किसी सरणी के लिए केवल एक संकेतक, यह घोषणा अवैध है।

अवैध संयोजन में शामिल हैं:

[]() - cannot have an array of functions
()() - cannot have a function that returns a function
()[] - cannot have a function that returns an array

उपरोक्त सभी मामलों में, आपको कानूनी होने की घोषणा के लिए इन () और [] दाईं ओर के प्रतीकों [] बीच बाईं ओर * प्रतीक को बांधने के लिए कोष्ठकों के एक सेट की आवश्यकता होगी।

यहाँ कुछ और उदाहरण दिए गए हैं:


कानूनी

int i;               an int
int *p;              an int pointer (ptr to an int)
int a[];             an array of ints
int f();             a function returning an int
int **pp;            a pointer to an int pointer (ptr to a ptr to an int)
int (*pa)[];         a pointer to an array of ints
int (*pf)();         a pointer to a function returning an int
int *ap[];           an array of int pointers (array of ptrs to ints)
int aa[][];          an array of arrays of ints
int *fp();           a function returning an int pointer
int ***ppp;          a pointer to a pointer to an int pointer
int (**ppa)[];       a pointer to a pointer to an array of ints
int (**ppf)();       a pointer to a pointer to a function returning an int
int *(*pap)[];       a pointer to an array of int pointers
int (*paa)[][];      a pointer to an array of arrays of ints
int *(*pfp)();       a pointer to a function returning an int pointer
int **app[];         an array of pointers to int pointers
int (*apa[])[];      an array of pointers to arrays of ints
int (*apf[])();      an array of pointers to functions returning an int
int *aap[][];        an array of arrays of int pointers
int aaa[][][];       an array of arrays of arrays of int
int **fpp();         a function returning a pointer to an int pointer
int (*fpa())[];      a function returning a pointer to an array of ints
int (*fpf())();      a function returning a pointer to a function returning an int

अवैध

int af[]();          an array of functions returning an int
int fa()[];          a function returning an array of ints
int ff()();          a function returning a function returning an int
int (*pfa)()[];      a pointer to a function returning an array of ints
int aaf[][]();       an array of arrays of functions returning an int
int (*paf)[]();      a pointer to a an array of functions returning an int
int (*pff)()();      a pointer to a function returning a function returning an int
int *afp[]();        an array of functions returning int pointers
int afa[]()[];       an array of functions returning an array of ints
int aff[]()();       an array of functions returning functions returning an int
int *fap()[];        a function returning an array of int pointers
int faa()[][];       a function returning an array of arrays of ints
int faf()[]();       a function returning an array of functions returning an int
int *ffp()();        a function returning a function returning an int pointer

स्रोत: http://ieng9.ucsd.edu/~cs30x/rt_lt.rule.html



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