2010-03-29 18 views
9

मैं निम्नलिखित हस्ताक्षर के साथ कार्य हो:असंगत सूचक प्रकार

void box_sort(int**, int, int) 

और चर निम्नलिखित प्रकार के:

int boxes[MAX_BOXES][MAX_DIMENSIONALITY+1] 

जब मैं समारोह बोल रहा हूँ

box_sort(boxes, a, b) 

जीसीसी मुझे देता है दो चेतावनियां:

103.c:79: warning: passing argument 1 of ‘box_sort’ from incompatible pointer type (string where i am calling the function) 
103.c:42: note: expected ‘int **’ but argument is of type ‘int (*)[11] (string where the function is defined) 

प्रश्न है क्यों? चाहे int x [] [] और int ** x (और वास्तव में int * x []) सी में समान प्रकार नहीं हैं?

+0

'MAX_BOXES' और' MAX_DIMENSIONALITY' क्या हैं? क्या वे मैक्रोज़, स्थिरांक, ... हैं? – Jacob

उत्तर

13

मुझे पता है कि लगभग दो दिन पहले इस तरह एक प्रश्न था ... हालांकि इसे अभी नहीं मिला।

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

int a[2][2]: 

__a[0][0]__|__a[0][1]__|__a[1][0]__|__a[1][1]__ 
    (int)  (int)  (int)  (int) 

int **a (e.g. dynamically allocated with nested mallocs) 

__a__ 
(int**) 
    | 
    v 
__a[0]__|__a[1]__ 
    (int*) (int*) 
    |  | 
    |  | 
    v  ------------------> 
__a[0][0]__|__a[0][1]__  __a[1][0]__|__a[1][1]__ 
    (int)  (int)    (int)  (int) 

आप का निर्माण कर सकता है एक दूसरे के इस तरह::

int **a = malloc(2 * sizeof(int*)); 
a[0] = malloc(2 * sizeof(int)); 
a[1] = malloc(2 * sizeof(int)); 

नोट: दूसरों के रूप में उल्लेख किया है, int[][] प्रतिसाद नहीं

यहाँ क्या वे एक 2x2 सरणी के लिए स्मृति में की तरह लग रही करेंगे एक वास्तविक प्रकार नहीं है; आकारों में से केवल एक निर्दिष्ट नहीं किया जा सकता है। लेकिन यहां सवाल का मूल यह है कि क्या एक द्वि-आयामी सरणी और एक डबल पॉइंटर एक ही चीज़ है।

+0

कूल ASCII-art भी देखें, लेकिन मुझे लगता है कि आपके पास तीर द्वारा इंगित बक्से के लिए पहला सूचकांक गलत है। –

+0

@RaphaelISP: धन्यवाद, बस एक कॉपी पेस्ट त्रुटि, जाहिर है। – Cascabel

+0

मुझे दृश्य स्पष्टीकरण पसंद है। मुझे आश्चर्य है कि, अगर उन्होंने * और [] के लिए इंटरचेंजबली काम करने के लिए यह संभव बना दिया है क्यों नहीं * {n} और [] {n} के लिए? क्या यह बहुत मुश्किल था? – NomeN

1

हस्ताक्षर की आवश्यकता के रूप में आपने कभी भी पॉइंटर्स की एक सरणी नहीं बनाई है।

सी में 2 डी सरणी करने के दो तरीके हैं। एक मामले में, आपके पास बस कुछ है और संकलक को बताया गया है कि आयाम क्या हैं। यह पंक्ति सूचकांक को कॉलम की संख्या से गुणा करके पंक्ति की शुरुआत की गणना करता है और फिर उस पंक्ति के भीतर तत्व ढूंढने के लिए कॉलम अनुक्रमणिका जोड़ता है।

दूसरा तरीका पॉइंटर्स के वेक्टर के साथ है, जहां कंपाइलर केवल पंक्ति की शुरुआत को खोजने के लिए वेक्टर को अस्वीकार करता है, लेकिन कंपाइलर इन्हें स्वचालित रूप से आपके लिए नहीं बनाएगा, आपको इसे स्वयं करना होगा।

आपकी वास्तविक वस्तु पहली तरह में से एक है, लेकिन आपका फ़ंक्शन प्रोटोटाइप दूसरी तरह से पूछ रहा है।

तो आपको या तो ऑब्जेक्ट से मेल खाने के लिए प्रोटोटाइप बदलना चाहिए या फ़ंक्शन को पास करने के लिए पंक्ति पॉइंटर्स के वेक्टर बनाना चाहिए।

+1

अच्छी तरह से समझाया, DigitalRoss। अधिक जानकारी के लिए, http://c-faq.com/aryptr/index.html –

1

सी में int[][] के रूप में ऐसा कोई प्रकार नहीं है, केवल एक बहुआयामी सरणी का पहला भाग अनिर्दिष्ट किया जा सकता है। तो int[][5] ठीक है।

अन्य उत्तर यहां पोस्ट, अगर आप C99 उपयोग कर सकते हैं, तो आप आप क्या चाहते हैं पूरा करने के लिए चर सरणियों उपयोग कर सकते हैं के अलावा:

void box_sort(int N, int M, int x[M][N]); 

यह माइक्रोसॉफ्ट के विजुअल C++ को छोड़कर सबसे प्लेटफार्मों पर काम करेंगे।

0

जब अधिकांश संदर्भों में एक सरणी अभिव्यक्ति दिखाई देती है, तो इसका प्रकार "टी-एन-एलिमेंट सरणी" से "पॉइंटर टू टी" में परिवर्तित हो जाता है, और इसका मान सरणी में पहले तत्व के पते पर सेट होता है। इस नियम के अपवाद तब होते हैं जब सरणी अभिव्यक्ति sizeof या पता (&) ऑपरेटर का पता चलता है, या यदि सरणी अभिव्यक्ति एक स्ट्रिंग अक्षर का उपयोग घोषणा में किसी अन्य सरणी को प्रारंभ करने के लिए किया जा रहा है।

क्या यह आपके कोड के संदर्भ में इसका मतलब है कि box_sort करने के लिए अपने कॉल में, अभिव्यक्ति boxes के प्रकार परोक्ष M-element array of N-element array of int से pointer to N-element array of int, या int (*)[MAX_DIMENSIONALITY+1] को, बदल जाती है तो अपने समारोह की तरह पैरामीटर प्रकार की उम्मीद की जानी चाहिए:

void box_sort(int (*arr)[MAX_DIMENSIONALITY+1], int x, int y) 
{ 
    ... 
} 

int *a के बाद से और int a[] एक समारोह पैरामीटर घोषणा में पर्याय बन गया है, यह इस प्रकार है कि int (*a)[N]int a[][N] का पर्याय बन गया है, तो आप

के रूप में ऊपर लिख सकता है
void box_sort(int arr[][MAX_DIMENSIONALITY+1], int x, int y) 
{ 
} 

हालांकि मैं व्यक्तिगत रूप से सूचक संकेत पसंद करता हूं, क्योंकि यह अधिक सटीक रूप से दर्शाता है कि क्या हो रहा है। ध्यान दें कि आपके समारोह में, आप सामान्य रूप में arr सबस्क्रिप्ट होगा:

arr[x][y] = ...; 

के बाद से अभिव्यक्ति arr[x]*(arr + x) के बराबर है, सूचक परोक्ष dereferenced है।

आप मनमाने ढंग से आकार सरणियों पर काम करने के box_sort चाहते हैं (यानी, सरणियों जहां दूसरे आयाम जरूरी MAX_DIMENSIONALITY +1 नहीं है), तो एक दृष्टिकोण निम्न करने के लिए है:

int boxes[X][Y]; 
... 
box_sort (&boxes[0], X, Y, x, y); 
... 
void box_sort(int *arr, size_t rows, size_t cols, int x, int y) 
{ 
    ... 
    arr[x*cols + y] = ...; 
} 

मूल रूप से, आप int के 1-डी सरणी के रूप में boxes का इलाज कर रहे हैं और ऑफसेट को मैन्युअल रूप से गणना कर रहे हैं।

संबंधित मुद्दे