C से ptr तक के प्राकृतिक प्रकार के क्षय के साथ C में मानक सरणी उपयोग
@ कोई व्यक्ति यहां अपने महान उत्तर में सही ढंग से बताता है :
पैरामीटर के रूप में एक सरणी पास करते समय, यह
void arraytest(int a[])
इसका मतलब बिल्कुल वैसा ही है
void arraytest(int *a)
हालाँकि, मुझे यह भी जोड़ने दें कि उपरोक्त दो रूप भी:
मतलब बिल्कुल वैसा ही
void arraytest(int a[0])
जिसका अर्थ है बिल्कुल वैसा ही
void arraytest(int a[1])
जिसका अर्थ है बिल्कुल वैसा ही
void arraytest(int a[2])
जिसका अर्थ है बिल्कुल वैसा ही
void arraytest(int a[1000])
आदि।
ऊपर दिए गए सरणी उदाहरणों में से हर एक में, इनपुट पैरामीटर प्रकार एक के लिए तयint *
हो जाता है, और बिना किसी चेतावनी और बिना किसी त्रुटि के कॉल किया जा सकता है, यहां तक कि निर्मित विकल्पों के साथ भी -Wall -Wextra -Werror
चालू ( इन 3 बिल्ड विकल्पों पर विवरण के लिए मेरा रेपो देखें ), जैसे यह:
int array1[2];
int * array2 = array1;
arraytest(array1);
arraytest(array2);
तथ्य की बात के रूप में, "आकार" मूल्य ( [0]
, [1]
, [2]
, [1000]
, आदि) सरणी पैरामीटर के अंदर यहां सौंदर्य / स्व-प्रलेखन प्रयोजनों के लिए जाहिरा तौर पर सिर्फ है, और किसी भी पूर्णांक सकारात्मक हो सकता है ( size_t
टाइप मुझे लगता है कि) आप चाहते हैं!
व्यवहार में, हालांकि, आपको इसका उपयोग उस सरणी के न्यूनतम आकार को निर्दिष्ट करने के लिए करना चाहिए जिसे आप फ़ंक्शन को प्राप्त करने की अपेक्षा करते हैं, ताकि कोड लिखते समय आपके लिए ट्रैक करना और सत्यापित करना आसान हो। मिश्रा सी 2012 मानक ( खरीद / £ 15.00 यहाँ डाउनलोड मानक के 236-पीजी 2012 संस्करण पीडीएफ ) अब तक राज्य (जोर जोड़ा) के रूप में चला जाता है:
नियम 17.5 एक सरणी प्रकार के लिए घोषित पैरामीटर के अनुरूप फ़ंक्शन तर्क में उपयुक्त तत्वों की संख्या होगी।
...
यदि किसी पैरामीटर को एक निर्दिष्ट आकार के साथ एक सरणी के रूप में घोषित किया जाता है, तो प्रत्येक फ़ंक्शन कॉल में संबंधित तर्क को उस ऑब्जेक्ट में इंगित करना चाहिए जिसमें कम से कम कई तत्व हैं, जैसे कि सरणी।
...
एक फ़ंक्शन पैरामीटर के लिए एक सरणी घोषणाकर्ता का उपयोग एक सूचक का उपयोग करने की तुलना में फ़ंक्शन इंटरफ़ेस को अधिक स्पष्ट रूप से निर्दिष्ट करता है। फ़ंक्शन द्वारा अपेक्षित तत्वों की न्यूनतम संख्या स्पष्ट रूप से बताई गई है, जबकि यह पॉइंटर के साथ संभव नहीं है।
दूसरे शब्दों में, वे स्पष्ट आकार प्रारूप का उपयोग करने की सलाह देते हैं, भले ही सी मानक तकनीकी रूप से इसे लागू नहीं करता है - यह कम से कम आपको डेवलपर के रूप में स्पष्ट करने में मदद करता है, और कोड का उपयोग करने वाले अन्य लोगों के लिए, फ़ंक्शन किस आकार की अपेक्षा कर रहा है। आप में पास होने के लिए
सी में सरणियों पर टाइप सुरक्षा को मजबूर करना
जैसा कि @Winger सेंडोन मेरे जवाब के नीचे एक टिप्पणी में बताते हैं, हम C को सरणी आकार के आधार पर एक सरणी प्रकार का इलाज करने के लिए बाध्य कर सकते हैं !
सबसे पहले, आपको यह समझना चाहिए कि मेरे उदाहरण में बस ऊपर, int array1[2];
इस तरह का उपयोग करना : अपने आप में क्षय होने का arraytest(array1);
कारण बनता array1
है int *
। फिर भी, यदि आप इसके बजाय पते लेते हैं array1
और कॉल करते हैं arraytest(&array1)
, तो आपको पूरी तरह से अलग व्यवहार मिलता है! अब, यह एक में क्षय नहीं करता है int *
! इसके बजाय, का प्रकार &array1
है int (*)[2]
, जिसका अर्थ है "सूचक int के आकार 2 की एक सरणी के लिए" , या "सूचक प्रकार के आकार 2 की एक सरणी के लिए सूचक" । इसलिए, आप किसी सरणी पर टाइप सेफ्टी के लिए C को फोर्स कर सकते हैं, जैसे:
void arraytest(int (*a)[2])
{
}
यह सिंटैक्स पढ़ना मुश्किल है, लेकिन फ़ंक्शन पॉइंटर के समान है । ऑनलाइन टूल, cdecl , हमें बताता है कि int (*a)[2]
इसका मतलब है: "int के सरणी 2 के रूप में एक पॉइंटर घोषित करें" (2 int
s की सरणी के लिए पॉइंटर )। : कोष्टक के बिना संस्करण के साथ इस भ्रमित न करें int * a[2]
, जो साधन: "पूर्णांक के लिए सूचक की सरणी 2 के रूप में एक घोषित" (2 की सरणी संकेत करने के लिए int
)।
अब, यह फ़ंक्शन आपको &
इनपुट ऑपरेटर के रूप में इस तरह के पते ऑपरेटर ( ) के साथ कॉल करने की आवश्यकता देता है , जो कोर के आकार के एक पैरामीटर के रूप में एक इनपुट पैरामीटर का उपयोग कर रहा है !:
int array1[2];
arraytest(&array1);
यह, हालांकि, एक चेतावनी का उत्पादन करेगा:
int array1[2];
arraytest(array1);
आप यहां इस कोड का परीक्षण कर सकते हैं ।
सी कंपाइलर को इस चेतावनी को एक त्रुटि में बदलने के लिए मजबूर करने के लिए, ताकि आप हमेशा arraytest(&array1);
केवल सही आकार के इनपुट सरणी का उपयोग करके कॉल करें और ( int array1[2];
इस मामले में), -Werror
अपने बिल्ड विकल्पों में जोड़ें । यदि onlinegdb.com पर ऊपर दिए गए टेस्ट कोड को चला रहे हैं, तो टॉप-राइट में गियर आइकन पर क्लिक करके यह विकल्प टाइप करने के लिए "अतिरिक्त कंपाइलर फ्लैग" पर क्लिक करें। अब, यह चेतावनी:
main.c:34:15: warning: passing argument 1 of ‘arraytest’ from incompatible pointer type [-Wincompatible-pointer-types]
main.c:24:6: note: expected ‘int (*)[2]’ but argument is of type ‘int *’
इस बिल्ड त्रुटि में बदल जाएगा:
main.c: In function ‘main’:
main.c:34:15: error: passing argument 1 of ‘arraytest’ from incompatible pointer type [-Werror=incompatible-pointer-types]
arraytest(array1);
^~~~~~
main.c:24:6: note: expected ‘int (*)[2]’ but argument is of type ‘int *’
void arraytest(int (*a)[2])
^~~~~~~~~
cc1: all warnings being treated as errors
ध्यान दें कि आप किसी दिए गए आकार के सरणियों के लिए "टाइप सेफ" पॉइंटर्स भी बना सकते हैं, जैसे:
int array[2];
int (*array_p)[2] = &array;
... लेकिन मैं यह जरूरी नहीं सुझाता , क्योंकि यह मुझे याद दिलाता है कि भाषा के वाक्यविन्यास जटिलता, क्रियात्मकता, और कठिनाई आर्किटेक्चरिंग कोड की असाधारण उच्च लागत पर, हर जगह टाइप सुरक्षा को मजबूर करने के लिए इस्तेमाल की जाने वाली C ++ हरकतों का एक बहुत कुछ है, और जो नापसंद है पहले के बारे में कई बार ranted है (उदाहरण के लिए: "C ++ पर मेरे विचार" यहां देखें )।
अतिरिक्त परीक्षणों और प्रयोग के लिए, नीचे दिए गए लिंक को भी देखें।
संदर्भ
ऊपर लिंक देखें। इसके अलावा:
- मेरा कोड प्रयोग ऑनलाइन: https://onlinegdb.com/B1RsrBDFD