खोज…


परिचय

एरे को डेटा प्रकार से प्राप्त किया जाता है, एक अन्य प्रकार के मूल्यों ("तत्वों") के आदेशित संग्रह का प्रतिनिधित्व करता है। सी में अधिकांश सरणियों में किसी एक प्रकार के तत्वों की एक निश्चित संख्या होती है, और इसका प्रतिनिधित्व तत्वों को बिना अंतराल या पैडिंग के स्मृति में संचित करता है। C बहुआयामी सरणियों की अनुमति देता है जिनके तत्व अन्य सरणियाँ हैं, और बिंदुओं के सरणियाँ भी हैं।

C गतिशील रूप से आवंटित सरणियों का समर्थन करता है जिसका आकार रन टाइम पर निर्धारित होता है। C99 और बाद में परिवर्तनशील लंबाई सरणियों या VLAs का समर्थन करता है।

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

  • नाम टाइप [लंबाई]; / * नाम 'नाम' और लंबाई 'लंबाई' के साथ 'प्रकार' की परिभाषा परिभाषित करें। * /
  • int गिरफ्तारी [10] = {0}; / * एक सरणी को परिभाषित करें और सभी तत्वों को 0. * / से प्रारंभ करें
  • int arr [10] = {42}; / * एक सरणी को परिभाषित करें और 1 तत्व को 42 से शुरू करें बाकी को 0. * /
  • int arr [] = {4, 2, 3, 1}; / * लंबाई की एक सरणी को परिभाषित और आरंभ करें 4. * /
  • arr [n] = value; / * इंडेक्स एन पर मूल्य सेट करें। * /
  • मूल्य = गिरफ्तारी [एन]; / * इंडेक्स एन पर मूल्य प्राप्त करें। * /

टिप्पणियों

हमें सरणियों की आवश्यकता क्यों है?

Arrays वस्तुओं को अपने स्वयं के महत्व के साथ व्यवस्थित करने का एक तरीका प्रदान करता है। उदाहरण के लिए, C तार वर्ण ( char s) के सरणियाँ हैं, और "Hello, World!" एक समुच्चय के रूप में अर्थ है जो कि वर्णों में अंतर्निहित नहीं है। इसी तरह, सरणियों का उपयोग आमतौर पर गणितीय वैक्टर और मैट्रिस का प्रतिनिधित्व करने के लिए किया जाता है, साथ ही साथ कई प्रकारों की सूची भी। इसके अलावा, तत्वों को समूहीकृत करने के कुछ तरीके के बिना, प्रत्येक को अलग-अलग चर के माध्यम से व्यक्तिगत रूप से संबोधित करने की आवश्यकता होगी। इतना ही नहीं, यह अजीब है, यह आसानी से विभिन्न लंबाई के संग्रह को समायोजित नहीं करता है।

अधिकांश संदर्भों में एरे को संक्षेप में पॉइंटर्स में बदल दिया जाता है

जब की संकार्य रूप में प्रदर्शित होने के अलावा sizeof ऑपरेटर, _Alignof ऑपरेटर (C2011), या एकल & (पता-के) ऑपरेटर, या एक स्ट्रिंग एक (अन्य) सरणी को प्रारंभ करने के लिए इस्तेमाल शाब्दिक रूप में, एक सरणी परोक्ष में बदल जाता है ( "पहले तत्व के लिए एक संकेतक" "का फैसला करता है"। इस निहित रूपांतरण को आसानी से सरणी सबस्क्रिप्टिंग ऑपरेटर ( [] ) की परिभाषा से जोड़ा जाता है: अभिव्यक्ति arr[idx] को *(arr + idx) बराबर परिभाषित किया गया है। इसके अलावा, चूंकि सूचक अंकगणितीय है, इसलिए *(arr + idx) भी *(idx + arr) बराबर है, जो बदले में idx[arr] बराबर है। उन सभी अभिव्यक्तियों को मान्य किया गया है और एक ही मूल्य का मूल्यांकन करते हैं, बशर्ते कि idx या arr एक सूचक (या एक सरणी है, जो एक सूचक के बराबर है), दूसरा एक पूर्णांक है, और पूर्णांक सरणी में एक वैध सूचकांक है जो सूचक को इंगित करता है।

एक विशेष मामले के रूप में, यह देखें कि &(arr[0]) &*(arr + 0) बराबर है, जो गिरफ्तारी को सरल arr । उन सभी अभिव्यक्तियों को विनिमेय किया जाता है जहां अंतिम सूचक को इंगित करता है। यह बस फिर से व्यक्त करता है कि एक सरणी एक पॉइंटर को उसके पहले तत्व के लिए तय करता है।

इसके विपरीत, यदि ऑपरेटर का पता-प्रकार T[N] ( यानी &arr ) प्रकार पर लागू होता है, तो परिणाम में T (*)[N] टाइप होता है और पूरे सरणी को इंगित करता है। यह कम से कम पॉइंटर अंकगणित के संबंध में एक सूचक से पहले सरणी तत्व के लिए अलग है, जो कि इंगित किए गए प्रकार के आकार के संदर्भ में परिभाषित किया गया है।

फ़ंक्शन पैरामीटर सरणियाँ नहीं हैं

void foo(int a[], int n);
void foo(int *a, int n);

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

किसी सरणी की घोषणा करना और आरंभ करना

एक आयामी सरणी घोषित करने के लिए सामान्य वाक्यविन्यास है

type arrName[size];

जहाँ type कोई भी अंतर्निहित प्रकार या उपयोगकर्ता-परिभाषित प्रकार हो सकता है जैसे संरचनाएं, arrName एक उपयोगकर्ता-निर्धारित पहचानकर्ता है, और size पूर्णांक स्थिरांक है।

एक सरणी की घोषणा (इस मामले में 10 इंट चर का एक सरणी) इस तरह किया जाता है:

int array[10];

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

int array[10] = {0};

Arrays में इनिशियलाइज़र भी हो सकते हैं, यह उदाहरण 10 int की सारणी की घोषणा करता है, जहाँ पहले 3 int 1 , 2 , 3 मान होगा, अन्य सभी मान शून्य होंगे:

int array[10] = {1, 2, 3};

आरंभीकरण की उपरोक्त विधि में, सूची में पहला मान सरणी के पहले सदस्य को सौंपा जाएगा, दूसरा मूल्य सरणी के दूसरे सदस्य को सौंपा जाएगा और इसी तरह। यदि सूची आकार सरणी आकार से छोटा है, तो उपरोक्त उदाहरण में, सरणी के शेष सदस्यों को शून्य के लिए आरंभीकृत किया जाएगा। निर्दिष्ट सूची आरोहण (ISO C99) के साथ, सरणी सदस्यों का स्पष्ट रूप से प्रारंभिककरण संभव है। उदाहरण के लिए,

int array[5] = {[2] = 5, [1] = 2, [4] = 9}; /* array is {0, 2, 5, 0, 9} */

ज्यादातर मामलों में, कंपाइलर आपके लिए सरणी की लंबाई को कम कर सकता है, इसे वर्ग कोष्ठक खाली छोड़ कर प्राप्त किया जा सकता है:

int array[] = {1, 2, 3}; /* an array of 3 int's */
int array[] = {[3] = 8, [0] = 9}; /* size is 4 */

शून्य लंबाई की एक सरणी घोषित करने की अनुमति नहीं है।

C99 C11

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

size_t m = calc_length(); /* calculate array length at runtime */
int vla[m];               /* create array with calculated length */

महत्वपूर्ण:

वीएलए के संभावित खतरनाक हैं। यदि उपर्युक्त उदाहरण में सरणी vla को स्टैक पर अधिक स्थान की आवश्यकता है, तो स्टैक ओवरफ्लो हो जाएगा। वीएलए का उपयोग अक्सर शैली गाइड और पुस्तकों और अभ्यासों द्वारा हतोत्साहित किया जाता है।

समाशोधन सरणी सामग्री (शून्यिंग)

आरंभीकरण के बाद कभी-कभी किसी सरणी को शून्य पर सेट करना आवश्यक होता है।

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

#define ARRLEN (10)

int main(void)
{
  int array[ARRLEN]; /* Allocated but not initialised, as not defined static or global. */

  size_t i;
  for(i = 0; i < ARRLEN; ++i)
  {
    array[i] = 0;
  }

  return EXIT_SUCCESS;
}

उपरोक्त लूप के लिए एक सामान्य शॉर्ट कट <string.h> memset() <string.h> से memset() का उपयोग memset() । नीचे दिखाए गए अनुसार पासिंग array अपने 1 तत्व के लिए एक पॉइंटर को क्षय करता है।

memset(array, 0, ARRLEN * sizeof (int)); /* Use size explicitly provided type (int here). */

या

memset(array, 0, ARRLEN * sizeof *array); /* Use size of type the pointer is pointing to. */

इस उदाहरण में के रूप में array (देखें एक सरणी और नहीं एक सरणी के 1 तत्व करने के लिए सिर्फ एक सूचक है सरणी लंबाई करने के लिए 0 से बाहर सरणी संभव है एक तीसरा विकल्प यह क्यों महत्वपूर्ण है पर):

 memset(array, 0, sizeof array); /* Use size of the array itself. */

अर्रे लंबाई

Arrays की निश्चित लंबाई है जो उनकी घोषणाओं के दायरे में जानी जाती है। फिर भी, सरणी लंबाई की गणना करना संभव और कभी-कभी सुविधाजनक होता है। विशेष रूप से, यह कोड को और अधिक लचीला बना सकता है जब सरणी लंबाई एक इनिशलाइज़र से स्वचालित रूप से निर्धारित की जाती है:

int array[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

/* size of `array` in bytes */
size_t size = sizeof(array);

/* number of elements in `array` */
size_t length = sizeof(array) / sizeof(array[0]); 

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

उदाहरण के लिए, मान लीजिए हम की एक सरणी के अंतिम तत्व वापस जाने के लिए एक समारोह लिखना चाहते int । ऊपर से जारी रखते हुए, हम इसे इस तरह कह सकते हैं:

/* array will decay to a pointer, so the length must be passed separately */
int last = get_last(array, length);

समारोह को इस तरह लागू किया जा सकता है:

int get_last(int input[], size_t length) {
    return input[length - 1];
}

विशेष रूप से ध्यान दें कि यद्यपि पैरामीटर input की घोषणा एक सरणी से मिलती जुलती है, यह वास्तव में input को पॉइंटर ( int ) के रूप में घोषित करता है । यह int *input रूप में input घोषित करने के बराबर है। यदि एक आयाम दिया जाता है, तो भी यह सच होगा। यह संभव है क्योंकि एरे कभी फ़ंक्शन के लिए वास्तविक तर्क नहीं हो सकते हैं (जब वे फ़ंक्शन कॉल एक्सप्रेशन में प्रकट होते हैं तो संकेत करने के लिए क्षय होते हैं), और इसे mnemonic के रूप में देखा जा सकता है।

यह एक पॉइंटर से सरणी आकार को निर्धारित करने का प्रयास करने के लिए एक बहुत ही सामान्य त्रुटि है, जो काम नहीं कर सकता है। यह मत करो:

int BAD_get_last(int input[]) {
    /* INCORRECTLY COMPUTES THE LENGTH OF THE ARRAY INTO WHICH input POINTS: */
    size_t length = sizeof(input) / sizeof(input[0]));

    return input[length - 1];  /* Oops -- not the droid we are looking for */
}

वास्तव में, वह विशेष त्रुटि इतनी सामान्य है कि कुछ संकलक इसे पहचानते हैं और इसके बारे में चेतावनी देते हैं। उदाहरण के लिए, clang , निम्नलिखित चेतावनी का उत्सर्जन करेगा:

warning: sizeof on array function parameter will return size of 'int *' instead of 'int []' [-Wsizeof-array-argument]
        int length = sizeof(input) / sizeof(input[0]);
                           ^
note: declared here
int BAD_get_last(int input[])
                     ^

सरणियों में मान सेट करना

एक्सेस ऐरे वैल्यूज़ को आमतौर पर स्क्वायर ब्रैकेट के माध्यम से किया जाता है:

int val;
int array[10];

/* Setting the value of the fifth element to 5: */
array[4] = 5;

/* The above is equal to: */
*(array + 4) = 5;

/* Reading the value of the fifth element: */
val = array[4];

परिचालकों के साइड इफेक्ट के रूप में + ऑपरेटर को विनिमेय होने के कारण (-> कम्यूटेटिव कानून) निम्नलिखित समतुल्य है:

*(array + 4) = 5;
*(4 + array) = 5;

तो साथ ही साथ अगले कथन समतुल्य हैं:

array[4] = 5;
4[array] = 5; /* Weird but valid C ... */

और उन दो के रूप में अच्छी तरह से:

val = array[4];
val = 4[array]; /* Weird but valid C ... */

सी कोई सीमा जाँच नहीं करता है, घोषित सरणी से बाहर की सामग्री को एक्सेस करना अपरिभाषित है ( आवंटित चंक से परे मेमोरी को एक्सेस करना ):

int val;
int array[10];

array[4] = 5;    /* ok */
val = array[4];  /* ok */
array[19] = 20;  /* undefined behavior */
val = array[15]; /* undefined behavior */

ऐरे और डेफिनेशन ऐरे एलिमेंट को परिभाषित करें

#include <stdio.h>
 
#define ARRLEN (10)

int main (void) 
{

   int n[ ARRLEN ]; /* n is an array of 10 integers */
   size_t i, j; /* Use size_t to address memory, that is to index arrays, as its guaranteed to 
                   be wide enough to address all of the possible available memory. 
                   Using signed integers to do so should be considered a special use case, 
                   and should be restricted to the uncommon case of being in the need of 
                   negative indexes. */
 
   /* Initialize elements of array n. */         
   for ( i = 0; i < ARRLEN ; i++ ) 
   {
      n[ i ] = i + 100; /* Set element at location i to i + 100. */
   }
   
   /* Output each array element's value. */
   for (j = 0; j < ARRLEN ; j++ ) 
   {
      printf("Element[%zu] = %d\n", j, n[j] );
   }
 
   return 0;
}

उपयोगकर्ता परिभाषित आकार के साथ एक सरणी को आवंटित और शून्य-प्रारंभ करें

#include <stdio.h>
#include <stdlib.h>


int main (void)
{
  int * pdata;
  size_t n;

  printf ("Enter the size of the array: ");
  fflush(stdout); /* Make sure the prompt gets printed to buffered stdout. */

  if (1 != scanf("%zu", &n)) /* If zu is not supported (Windows?) use lu. */
  {
    fprintf("scanf() did not read a in proper value.\n");
    exit(EXIT_FAILURE);
  }

  pdata = calloc(n, sizeof *pdata);
  if (NULL == pdata) 
  {
    perror("calloc() failed"); /* Print error. */
    exit(EXIT_FAILURE);
  }

  free(pdata); /* Clean up. */

  return EXIT_SUCCESS;
}

इस कार्यक्रम की कोशिश करता मानक इनपुट से एक अहस्ताक्षरित पूर्णांक मान में स्कैन करने के लिए, की एक सरणी के लिए स्मृति का एक ब्लॉक का आवंटन n प्रकार के तत्वों int को फोन करके calloc() समारोह। स्मृति को उत्तरार्द्ध द्वारा सभी शून्य में आरंभीकृत किया जाता है।

सफलता के मामले में मेमोरी को कॉल टू free() द्वारा जारी किया जाता है।

एक सरणी के माध्यम से कुशलतापूर्वक और पंक्ति-प्रमुख क्रम में फेरबदल करना

C में Arrays को स्मृति के एक सन्निहित भाग के रूप में देखा जा सकता है। अधिक सटीक रूप से, सरणी का अंतिम आयाम सन्निहित भाग है। इसे हम पंक्ति-प्रमुख क्रम कहते हैं । इस तथ्य और इस तथ्य को समझते हुए कि बाद में कैश के दोषों को रोकने के लिए अनचाहे डेटा तक पहुँचने पर कैश फॉल्ट कैश में एक पूर्ण कैश लाइन को लोड करता है, हम देख सकते हैं कि array[0][0] साथ आयाम १००००x१०००० की एक सरणी तक पहुंच क्यों संभावित रूप से लोड array[0][1] होगा array[0][1] कैश में, लेकिन array[1][0] एक्सेस करना array[1][0] सही होने के बाद दूसरा कैश फॉल्ट उत्पन्न करेगा, क्योंकि यह sizeof(type)*10000 बाइट्स array[0][0] से दूर है array[0][0] , और इसलिए निश्चित रूप से नहीं उसी कैश लाइन पर। यही कारण है कि इस तरह से यह अक्षम है:

#define ARRLEN 10000
int array[ARRLEN][ARRLEN];

size_t i, j;
for (i = 0; i < ARRLEN; ++i)
{
    for(j = 0; j < ARRLEN; ++j)
    {
        array[j][i] = 0;
    }
}

और इस तरह पुनरावृत्ति अधिक कुशल है:

#define ARRLEN 10000
int array[ARRLEN][ARRLEN];

size_t i, j;
for (i = 0; i < ARRLEN; ++i)
{
    for(j = 0; j < ARRLEN; ++j)
    {
        array[i][j] = 0;
    }
}

एक ही नस में, यही कारण है कि जब एक आयाम और एकाधिक अनुक्रमित के साथ एक सरणी से निपटते हैं (आइए इंडेक्स और जे के साथ सादगी के लिए यहां 2 आयाम कहते हैं) इस तरह से सरणी के माध्यम से पुनरावृति करना महत्वपूर्ण है:

#define DIM_X 10
#define DIM_Y 20

int array[DIM_X*DIM_Y];

size_t i, j;
for (i = 0; i < DIM_X; ++i)
{
    for(j = 0; j < DIM_Y; ++j)
    {
        array[i*DIM_Y+j] = 0;
    }
}

या 3 आयामों और अनुक्रमित के साथ i, j और k:

#define DIM_X 10
#define DIM_Y 20
#define DIM_Z 30

int array[DIM_X*DIM_Y*DIM_Z];

size_t i, j, k;
for (i = 0; i < DIM_X; ++i)
{
    for(j = 0; j < DIM_Y; ++j)
    {
        for (k = 0; k < DIM_Z; ++k)
        {
            array[i*DIM_Y*DIM_Z+j*DIM_Z+k] = 0;
        }
    }
}

या अधिक सामान्य तरीके से, जब हमारे पास N1 x N2 x के साथ एक सरणी है ... x nd तत्व, d आयाम और सूचकांक n1, n2, ... के रूप में नोट किया गया है , तो nd ऑफ़सेट की गणना इस तरह की जाती है।

सूत्र

चित्र / सूत्र से लिया गया: https://en.wikipedia.org/wiki/Row-major_order

बहुआयामी सरणियाँ

C प्रोग्रामिंग भाषा बहुआयामी सरणियों की अनुमति देती है। यहाँ एक बहुआयामी सरणी घोषणा का सामान्य रूप है -

type name[size1][size2]...[sizeN];

उदाहरण के लिए, निम्नलिखित घोषणा एक तीन आयामी (5 x 10 x 4) पूर्णांक सरणी बनाती है:

int arr[5][10][4];

द्वि-आयामी अर्रे

बहुआयामी सरणी का सबसे सरल रूप द्वि-आयामी सरणी है। एक द्वि-आयामी सरणी, संक्षेप में, एक-आयामी सरणियों की एक सूची है। आयामों के द्वि-आयामी पूर्णांक सरणी को घोषित करने के लिए, हम निम्नानुसार लिख सकते हैं:

type arrayName[m][n];

जहाँ type कोई भी मान्य C डेटा प्रकार ( int , float , आदि) और arrayName किसी भी मान्य C पहचानकर्ता हो सकता है। एक दो आयामी सरणी को m पंक्तियों और n कॉलम के साथ एक तालिका के रूप में कल्पना की जा सकती है। नोट: सरणी सी में फर्क पड़ता है int a[4][3] सरणी के समान नहीं है int a[3][4] । पंक्तियों की संख्या पहले आती है क्योंकि C एक पंक्ति -मेजर भाषा है।

एक दो आयामी सरणी a , जिसमें तीन पंक्तियाँ होती हैं और चार कॉलम निम्नानुसार दिखाए जा सकते हैं:

तालिका के रूप में 2 डी सरणी का दृश्य लेआउट

इस प्रकार, सरणी में प्रत्येक तत्व a फार्म का एक तत्व नाम से पहचाना जाता है a[i][j] जहां, a सरणी का नाम है, i जो पंक्ति का प्रतिनिधित्व करता है, और j जो स्तंभ प्रतिनिधित्व करता है। याद रखें कि पंक्तियाँ और स्तंभ शून्य अनुक्रमित हैं। यह 2-डी मेट्रिसेस को सबस्क्रिप्ट करने के लिए गणितीय संकेतन के समान है।

दो आयामी आयामों की शुरुआत

प्रत्येक पंक्ति के लिए ब्रैकेटेड मान निर्दिष्ट करके बहुआयामी सरणियों को आरंभ किया जा सकता है। निम्नलिखित 3 पंक्तियों के साथ एक सरणी को परिभाषित करता है जहां प्रत्येक पंक्ति में 4 कॉलम होते हैं।

int a[3][4] = {  
   {0, 1, 2, 3} ,   /*  initializers for row indexed by 0 */
   {4, 5, 6, 7} ,   /*  initializers for row indexed by 1 */
   {8, 9, 10, 11}   /*  initializers for row indexed by 2 */
};

नेस्टेड ब्रेसिज़, जो इच्छित पंक्ति को इंगित करते हैं, वैकल्पिक हैं। निम्नलिखित आरंभीकरण पिछले उदाहरण के बराबर है:

int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};

जबकि नेस्टेड ब्रेसिज़ के साथ ऐरे बनाने की विधि वैकल्पिक है, यह अधिक पठनीय और स्पष्ट होने के कारण दृढ़ता से प्रोत्साहित किया जाता है।

दो-आयामी सरणी तत्वों तक पहुंचना

दो-आयामी सरणी में एक तत्व को सब्सक्राइबर्स, अर्थात, पंक्ति सूचकांक और सरणी के कॉलम इंडेक्स का उपयोग करके एक्सेस किया जाता है। उदाहरण के लिए -

int val = a[2][3];

उपरोक्त कथन सरणी की तीसरी पंक्ति से 4 तत्व को ले जाएगा। आइए हम निम्नलिखित कार्यक्रम की जाँच करें जहाँ हमने दो आयामी सरणी को संभालने के लिए नेस्टेड लूप का उपयोग किया है:

#include <stdio.h>
 
int main () {

   /* an array with 5 rows and 2 columns*/
   int a[5][2] = { {0,0}, {1,2}, {2,4}, {3,6},{4,8}};
   int i, j;
 
   /* output each array element's value */
   for ( i = 0; i < 5; i++ ) {

      for ( j = 0; j < 2; j++ ) {
         printf("a[%d][%d] = %d\n", i,j, a[i][j] );
      }
   }
   
   return 0;
}

जब उपरोक्त कोड संकलित और निष्पादित किया जाता है, तो यह निम्नलिखित परिणाम उत्पन्न करता है:

a[0][0]: 0
a[0][1]: 0
a[1][0]: 1
a[1][1]: 2
a[2][0]: 2
a[2][1]: 4
a[3][0]: 3
a[3][1]: 6
a[4][0]: 4
a[4][1]: 8

तीन-आयामी सरणी:

एक 3 डी सरणी अनिवार्य रूप से सरणियों के सरणी का एक सरणी है: यह एक सरणी या 2 डी सरणियों का संग्रह है, और एक 2 डी सरणी 1 डी सरणियों का एक सरणी है।

तालिकाओं के संग्रह के रूप में 2 डी सरणी का दृश्य लेआउट

3 डी सरणी मेमोरी मैप:

3 डी सरणी स्मृति में आकस्मिक रूप से रखी गई है

एक 3D ऐरे की शुरुआत:

double cprogram[3][2][4]={ 
{{-0.1, 0.22, 0.3, 4.3}, {2.3, 4.7, -0.9, 2}},
 {{0.9, 3.6, 4.5, 4}, {1.2, 2.4, 0.22, -1}},
 {{8.2, 3.12, 34.2, 0.1}, {2.1, 3.2, 4.3, -2.0}} 
};

हम किसी भी संख्या के आयामों के साथ सरणियाँ हो सकते हैं, हालांकि यह संभावना है कि बनाए गए अधिकांश सरणियों में से एक या दो आयाम होंगे।

संकेत का उपयोग कर एक सरणी के माध्यम से Iterating

#include <stdio.h>
#define SIZE (10)
int main()
{
    size_t i = 0;
    int *p = NULL;
    int a[SIZE];
    
    /* Setting up the values to be i*i */
    for(i = 0; i < SIZE; ++i) 
    {
        a[i] = i * i;
    }
    
    /* Reading the values using pointers */
    for(p = a; p < a + SIZE; ++p) 
    {
        printf("%d\n", *p);
    }

    return 0;
}

यहाँ, के प्रारंभ में p पहले में for लूप हालत, सरणी a decays अपनी पहली तत्व के लिए सूचक है, के रूप में यह लगभग सभी स्थानों पर जहां इस तरह के एक सरणी चर प्रयोग किया जाता है जाएगा।

फिर, ++p सूचक p पर अंकगणित करता है और सरणी के तत्वों के माध्यम से एक-एक करके चलता है, और उन्हें *p साथ dereferencing द्वारा संदर्भित करता है।

एक फ़ंक्शन के लिए बहुआयामी सरणियों को पास करना

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

#include <assert.h>
#include <stdlib.h>

/* When passing a multidimensional array (i.e. an array of arrays) to a
   function, it decays into a pointer to the first element as usual.  But only
   the top level decays, so what is passed is a pointer to an array of some fixed
   size (4 in this case). */
void f(int x[][4]) {
    assert(sizeof(*x) == sizeof(int) * 4);
}

/* This prototype is equivalent to f(int x[][4]).
   The parentheses around *x are required because [index] has a higher
   precedence than *expr, thus int *x[4] would normally be equivalent to int
   *(x[4]), i.e. an array of 4 pointers to int.  But if it's declared as a
   function parameter, it decays into a pointer and becomes int **x, 
   which is not compatable with x[2][4]. */
void g(int (*x)[4]) {
    assert(sizeof(*x) == sizeof(int) * 4);
}

/* An array of pointers may be passed to this, since it'll decay into a pointer
   to pointer, but an array of arrays may not. */
void h(int **x) {
    assert(sizeof(*x) == sizeof(int*));
}

int main(void) {
    int foo[2][4];
    f(foo);
    g(foo);

    /* Here we're dynamically creating an array of pointers.  Note that the 
       size of each dimension is not part of the datatype, and so the type 
       system just treats it as a pointer to pointer, not a pointer to array
       or array of arrays. */
    int **bar = malloc(sizeof(*bar) * 2);
    assert(bar);
    for (size_t i = 0; i < 2; i++) {
        bar[i] = malloc(sizeof(*bar[i]) * 4);
        assert(bar[i]);
    }

    h(bar);
    
    for (size_t i = 0; i < 2; i++) {
        free(bar[i]);
    }
    free(bar);
}

यह सभी देखें

अर्र्स टू फंक्शन्स में पास होना



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