Arrays और पॉइंटर्स पूरी तरह से अलग जानवर हैं। अधिकांश संदर्भों में, अभिव्यक्ति एक सरणी को नामित करने के लिए एक सूचक के रूप में माना जाता है।
सबसे पहले, एक छोटे से मानक भाषा (n1256):
6.3.2।1 Lvalues, सरणियों, और समारोह designators
...
जब यह
sizeof
ऑपरेटर या एकल
&
ऑपरेटर के संकार्य है, या एक स्ट्रिंग शाब्दिक एक सरणी प्रारंभ करने में इस्तेमाल किया, एक अभिव्यक्ति टाइप किया है सिवाय 3 "
प्रकार टाइप करें "पॉइंटर से
टाइप" जो कि सरणी ऑब्जेक्ट के प्रारंभिक तत्व को इंगित करता है और एक लवली नहीं है। यदि सरणी ऑब्जेक्ट में स्टोरेज क्लास पंजीकृत है, तो व्यवहार अपरिभाषित है।
स्ट्रिंग अक्षर "यह एक परीक्षण है" char
का 15-तत्व सरणी है। घोषणा में
char *string1 = "this is a test";
string1
को
char
पर सूचक के रूप में घोषित किया जा रहा है। उपर्युक्त भाषा के अनुसार,
अभिव्यक्ति का प्रकार "यह एक परीक्षण है"
char [15]
से
char *
में परिवर्तित किया गया है, और परिणामस्वरूप सूचक मान
string1
पर असाइन किया गया है।
घोषणा
char string2[] = "this is a test";
कुछ अलग होता है में । अधिक मानक भाषा:
6.7.8 प्रारंभ
...
14 चरित्र प्रकार की एक सरणी एक चरित्र स्ट्रिंग शाब्दिक द्वारा प्रारंभ किया जा सकता है, वैकल्पिक रूप से ब्रेसिज़ में संलग्न। चरित्र स्ट्रिंग शाब्दिक के लगातार वर्ण ( सहित कमरे में या यदि सरणी अज्ञात आकार का है तो शून्य वर्ण को समाप्त करना) सरणी के तत्वों को प्रारंभ करें।
...
22 यदि अज्ञात आकार की एक सरणी शुरू की गई है, तो इसका आकार एक स्पष्ट प्रारंभकर्ता के साथ सबसे बड़े अनुक्रमित तत्व द्वारा निर्धारित किया जाता है। इसकी प्रारंभकर्ता सूची के अंत में, सरणी में अपूर्ण प्रकार नहीं है।
इस मामले में, string2
char
की एक सरणी के रूप में घोषित किया जा रहा है, इसका आकार प्रारंभकर्ता की लंबाई से गणना की जाती है, और सामग्री स्ट्रिंग शाब्दिक की सरणी में कॉपी किया जाता है।
यहां एक काल्पनिक स्मृति नक्शा वर्णन करने के लिए क्या हो रहा है है:
Item Address 0x00 0x01 0x02 0x03
---- ------- ---- ---- ---- ----
no name 0x080't' 'h' 'i' 's'
0x080' ' 'i' 's' ' '
0x080'a' ' ' 't' 'e'
0x0800123C 's' 't' 0
...
string1 0x12340000 0x08 0x00 0x12 0x30
string2 0x12340004 't' 'h' 'i' 's'
0x12340008 ' ' 'i' 's' ' '
0x1234000C 'a' ' ' 't' 'e'
0x1234000F 's' 't' 0
स्ट्रिंग शाब्दिक स्थिर हद तक है, यानी, उनके लिए स्मृति प्रोग्राम स्टार्टअप पर अलग हो जाती है और प्रोग्राम समाप्त होने तक आयोजित होता है। एक स्ट्रिंग शाब्दिक सामग्री की सामग्री को संशोधित करने का प्रयास अपरिभाषित व्यवहार का आह्वान करता है; अंतर्निहित प्लेटफार्म इसे अनुमति दे सकता है या नहीं, और मानक संकलक पर कोई प्रतिबंध नहीं रखता है। यह कार्य करना सबसे अच्छा है जैसे कि शाब्दिक हमेशा अनचाहे होते हैं।
उपरोक्त मेरे मेमोरी मानचित्र में, स्ट्रिंग अक्षर का पता string1
और string2
के पते से कुछ हद तक सेट किया गया है।
वैसे भी, आप string1
देख सकते हैं, जिसमें एक सूचक प्रकार है, जिसमें पता स्ट्रिंग अक्षर का पता है। string2
, एक सरणी प्रकार होने के कारण, स्ट्रिंग अक्षर के सामग्री की एक प्रति शामिल है।
string2
के आकार संकलन समय पर ज्ञात है, sizeof
सरणी में आकार (बाइट्स की संख्या) देता है।
%i
रूपांतरण विनिर्देश size_t
प्रकार के अभिव्यक्तियों के लिए उपयोग करने के लिए सही नहीं है। यदि आप सी 99 में काम कर रहे हैं, तो %zu
का उपयोग करें। C89 में, आप %lu
का उपयोग करें और unsigned long
को अभिव्यक्ति डाली होगा:
C89: printf("%lu, %lu\n", (unsigned long) sizeof string1, (unsigned long) sizeof string2);
C99: printf("%zu, %zu\n", sizeof string1, sizeof string2);
ध्यान दें कि sizeof
एक ऑपरेटर, नहीं एक समारोह कॉल है, जब ऑपरेंड एक अभिव्यक्ति है जो ऑब्जेक्ट इंगित करती है, तो ब्रांड्स आवश्यक नहीं हैं (हालांकि वे चोट नहीं पहुंचाते हैं)।
इसके अलावा, 'आकार'' 'size_t' देता है, जो'% i' द्वारा अपेक्षित' int' के विपरीत हस्ताक्षरित नहीं है। 'Size_t' चर के लिए सही प्रारूप'% zu' है। –
ऐरे एक पिंटर नहीं है! उसे याद रखो! – Hauleth