क्या [] ऑपरेटर के बजाय सूचक अंकगणित के माध्यम से ऐरे तत्वों तक पहुंचने के लिए इसे संदर्भित करना बुरा है?


12

मैंने अभी C में प्रोग्राम करना सीखना शुरू किया है, और पॉइंटर्स और सरणियों के बारे में अपनी समझ को बेहतर बनाने के लिए, मैंने किसी भी पॉइंटर को बनाए बिना किसी ऐरे के तत्वों को संदर्भित करने का प्रयास किया है:

for(k1 = 0; k1 < ROW; k1++){
    for(k2 = 0; k2 < COLUMN; k2++){

        array[k1][k2] = k1*COLUMN + k2 + 1;

        printf("[%d][%d] = %d\n", k1, k2, *(array[k1] + k2));

    }
}

संपूर्ण कोड संकलित करता है और त्रुटिपूर्ण चलता है।

मुझे लगता है कि एक बड़े स्रोत कोड में हर एक सरणी के लिए एक पॉइंटर बनाने के लिए अत्यधिक अक्षम होना प्रतीत होता है।

तो, एक पॉइंटर का उपयोग करके संग्रहीत और पुनर्प्राप्त किए गए सरणी का पता रखने के बजाय, क्या यह सरणी के पते का सीधे उपयोग करने के लिए एक खराब प्रोग्रामिंग अभ्यास है, जैसा कि ऊपर दिखाया गया है?


उपयोग printf "[%d][%d] = %d\n", k1, k2, array[k1] [k2]));करने से सूचक अंकगणित से बच जाएगा और समझने में आसान होगा।
कैस्पर वैन डेन बर्ग

1
हाहा, तुम मुझे मिल गए। मैंने केवल एक प्रयोग के रूप में किया कि कैसे बेहतर संकेत और सरणियों के काम को समझने के लिए।
निको गैम्बट

सूचक अंकगणित वास्तव में सरणी अनुक्रमित का उपयोग करने की तुलना में लगभग 30% तेज है।
एंडी

जवाबों:


16

यह "खराब" है केवल उस सीमा तक जो कम पठनीय है। a[x]के रूप में एक ही बात है *(a+x), इसलिए दक्षता या व्यवहार में कोई अंतर नहीं है (वास्तव में, x[a]यह भी काम करेगा)। यह सिर्फ इतना a[x]है कि आम तौर पर हमारे लिए बहुत अधिक सहज है।

लेकिन यह कहना कि पठनीयता कोई बड़ी बात नहीं है। यह देखने के लिए कि आप कोड में उन्हें कैसे देखते हैं, इन दो अभिव्यक्तियों को "कैसे" पढ़ेंगे, इस बारे में सोचें:

  • *(a+x)= "सूचक aऔर पूर्णांक के योग द्वारा इंगित की गई बात x"
  • a[x]= " xसरणी का सदस्य a"

इसी तरह, जब आपको किसी ऐरे तत्व का पता बताना होता है:

  • (a+x)= "सूचक aऔर पूर्णांक का योग x"
  • &a[x]= " xसरणी के वें सदस्य का पता a"

अधिकांश समय, []संस्करणों को समझना आसान होता है जब आप गैर-तुच्छ कोड को कई अलग-अलग सरणियों (विशेष रूप से सरणियों के सरणियों) पर काम कर रहे होते हैं। इसलिए []ऑपरेटर पहले स्थान पर मौजूद है।

पुनश्च इस तरह की बात को कड़ाई से सीखना अभ्यास के रूप में करना बहुत अच्छा विचार है। यह समझना महत्वपूर्ण है कि सरणियाँ वास्तव में केवल संकेत और ऑफसेट हैं।


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

1
@NikoGambt आप हमेशा एक और सवाल पूछ सकते हैं =)
Ixrec

1
क्या मतलब है केवल हद तक ...? प्रोग्रामिंग भाषाओं का संपूर्ण बिंदु मनुष्यों को पढ़ने के लिए कोड को आसान बनाना है। अगर हम इस बारे में परवाह नहीं करते हैं, तो हम सभी हेक्साडेसिमल में ऑप कोड लिख रहे होंगे।
सोलोमन स्लो

2
Arrays संकेत नहीं हैं, बस संकेत क्षय करने के लिए क्षय।
कोडइन्चोस

4

हां, यह बुरा अभ्यास है, लेकिन अक्षमता कारणों से नहीं।

ऐरे ऑपरेटर हुड के नीचे सूचक अंकगणित का उपयोग करता है, इसलिए वे समान रूप से कुशल हैं।

सूचक अंकगणित के साथ समस्या यह है कि यह बहुत त्रुटि प्रवण है और पढ़ने में कठिन है।

अंगूठे का नियम: जब तक आपको नहीं करना है, तब तक अंकगणित का उपयोग न करें।


1
चूँकि यह किसी भी तरह से अंकगणित का उपयोग करता है, इसका मतलब यह नहीं है कि संकेत भी उतने ही त्रुटि-प्रवण और पढ़ने में कठिन हैं?
निको गम्बट

1
@ NikoGambt कंपाइलर हुड के नीचे पॉइंटर एरीथमिक करने में काफी अच्छे हैं और शायद ही कभी 'गलतियाँ' करेंगे; यह प्रोग्रामर है जो परिणाम के रूप में गंदा कीड़े के साथ गलतियाँ करेंगे।
कैस्पर वैन डेन बर्ग

@KaspervandenBerg हाँ, मैं सहमत हूँ। हालाँकि, मुझे प्रोग्रामर द्वारा की गई त्रुटियों में दिलचस्पी है, और मैं बिलकुल सुनिश्चित नहीं हूँ कि अगर मैं ऊपर वहाँ क्या किया है तो यह एक बुरा प्रोग्रामिंग अभ्यास है, ऐसे मामलों में जहां एक सरणी के पते को संदर्भित करने की आवश्यकता है। , अगर ऐसे मामले मौजूद हैं।
निको गम्बट

1
@NikoGambt कुछ लिखना जो प्रदर्शन के उद्देश्यों के लिए कम पठनीय है, लगभग हमेशा बुरा अभ्यास होता है, लेकिन ऐसा कुछ लिखना जो बिना किसी लाभ के कम पठनीय हो, वह असमान रूप से बुरा अभ्यास है।
नील

@ नील मेरा छोटा सा प्रयोग निरर्थक नहीं है। ऐसा करने से, मुझे पता चला कि संकलक बहु-आयामी सरणी को संदर्भित करने के लिए व्यूअर की एक सरणी बनाता है। हालाँकि, चूंकि आपने कहा था कि प्रदर्शन की तुलना में पठनीयता अधिक महत्वपूर्ण है, मुझे लगता है कि यह अभी भी एक बुरा प्रोग्रामिंग अभ्यास है।
निको गम्बट

0

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

int *array[]; //This is a array to pointers of type *int. 

array[k1] + k2; //This is pointer arithmetic on one pointer stored in the array  

इस सूचक को Dereferencing से आपके केवल गणना किए गए सूचक को इंगित करता है, को इंगित करता है। आप जो कर रहे हैं, उसे करने का कोई मतलब नहीं है। लेकिन आप सरणी को रैखिक कर सकते हैं और फिर इस तरह से एक स्ट्राइड कर सकते हैं।

int array[y_dim*x_dim]; 
int index = x_dim*y + x; 
array[index]; //Gives you the element in x, y!

उसे स्ट्राइड x_dim है। आशा है कि मेरा उत्तर स्पष्ट कर रहा है!


यह ओपी से स्पष्ट नहीं है कि यह एक का उपयोग करता है नहीं है int* array[ROW];एक int array[ROW][COLUMN];, या एक int (*array)[COLUMN];। ओपी में कोड के साथ इन तीन परिभाषाओं में से किसी का भी उपयोग किया जा सकता है।
सेंटास्टर - मोनिका

हाँ, मैं इस बात से अवगत हूँ, मेरा उत्तर उस बिंदु पर थोड़ा अनाड़ी है। मैंने इसे सही किया, धन्यवाद!
१ht:
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.