2010-12-07 15 views
5

संभव डुप्लिकेट:
What is the difference between char s[] and char *s in C?
Difference between char *str = “…” and char str[N] = “…”?प्रश्न

मैं कुछ कोड है कि मुझे हैरान किया गया है है।

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

int main(int argc, char *argv[]) 
{ 
    char* string1 = "this is a test"; 
    char string2[] = "this is a test"; 
    printf("%i, %i\n", sizeof(string1), sizeof(string2)); 
    system("PAUSE"); 
    return 0; 
} 

जब यह string1 के आकार आउटपुट, यह 4 प्रिंट है, जो उम्मीद की जा करने के लिए क्योंकि एक सूचक का आकार 4 बाइट्स है। लेकिन जब यह स्ट्रिंग 2 प्रिंट करता है, तो यह 15 आउटपुट करता है। मैंने सोचा कि एक सरणी एक सूचक था, तो स्ट्रिंग 2 का आकार स्ट्रिंग 1 के समान होना चाहिए? तो ऐसा क्यों है कि यह एक ही प्रकार के डेटा (सूचक) के लिए दो अलग-अलग आकारों को प्रिंट करता है?

+4

इसके अलावा, 'आकार'' 'size_t' देता है, जो'% i' द्वारा अपेक्षित' int' के विपरीत हस्ताक्षरित नहीं है। 'Size_t' चर के लिए सही प्रारूप'% zu' है। –

+0

ऐरे एक पिंटर नहीं है! उसे याद रखो! – Hauleth

उत्तर

5

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 यदि अज्ञात आकार की एक सरणी शुरू की गई है, तो इसका आकार एक स्पष्ट प्रारंभकर्ता के साथ सबसे बड़े अनुक्रमित तत्व द्वारा निर्धारित किया जाता है। इसकी प्रारंभकर्ता सूची के अंत में, सरणी में अपूर्ण प्रकार नहीं है।

इस मामले में, string2char की एक सरणी के रूप में घोषित किया जा रहा है, इसका आकार प्रारंभकर्ता की लंबाई से गणना की जाती है, और सामग्री स्ट्रिंग शाब्दिक की सरणी में कॉपी किया जाता है।

यहां एक काल्पनिक स्मृति नक्शा वर्णन करने के लिए क्या हो रहा है है:

 
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 एक ऑपरेटर, नहीं एक समारोह कॉल है, जब ऑपरेंड एक अभिव्यक्ति है जो ऑब्जेक्ट इंगित करती है, तो ब्रांड्स आवश्यक नहीं हैं (हालांकि वे चोट नहीं पहुंचाते हैं)।

+0

वाह! विस्तृत उत्तर के लिए धन्यवाद! यह वास्तव में मेरी मदद की। –

13

Arrays पॉइंटर्स नहीं हैं। कुछ स्थितियों में सरणी के पहले तत्व को इंगित करने के लिए क्षय: जब आप इसे किसी फ़ंक्शन पर पास करते हैं, जब आप इसे पॉइंटर इत्यादि देते हैं, लेकिन अन्यथा सरणी सरणी होती है - वे ढेर पर मौजूद होते हैं, संकलित करते हैं समय आकार जिन्हें sizeof, और अन्य सभी अच्छी चीजों के साथ निर्धारित किया जा सकता है।

4

string1 एक सूचक है, लेकिन string2 एक सरणी है।

दूसरी पंक्ति int a[] = { 1, 2, 3}; की तरह कुछ है जो लंबाई-3 सरणी (प्रारंभकर्ता के माध्यम से) होने के लिए a परिभाषित करती है।

string2 का आकार 15 है क्योंकि प्रारंभकर्ता शून्य-समाप्त होता है (इसलिए 15 स्ट्रिंग + 1 की लंबाई है)।

2

संकलक जानता है कि test2 एक सरणी है, इसलिए यह इसे आवंटित बाइट्स की संख्या प्रिंट करता है (14 अक्षरों और शून्य टर्मिनेटर)। याद रखें कि sizeof एक कंपाइलर फ़ंक्शन है, इसलिए यह एक स्टैक वैरिएबल के आकार को जान सकता है।

4

अज्ञात आकार की एक सरणी आकार के उद्देश्यों के लिए सूचक के बराबर है। स्थिर आकार का एक सरणी आकार के उद्देश्यों के लिए अपने स्वयं के प्रकार के रूप में गिना जाता है, और सरणी के लिए आवश्यक संग्रहण के आकार की रिपोर्ट करता है। भले ही string2 को स्पष्ट आकार के बिना आवंटित किया गया हो, सी संकलक इसे उद्धृत स्ट्रिंग द्वारा प्रत्यक्ष प्रारंभिकता के कारण जादूगर रूप से व्यवहार करता है और इसे स्थिर आकार के साथ एक सरणी में परिवर्तित करता है। (चूंकि मेमोरी किसी भी अन्य तरीके से आवंटित नहीं की जाती है, इसके बाद कुछ भी नहीं कर सकता है।) sizeof व्यवहार के उद्देश्य के लिए स्टेटिक आकार सरणी पॉइंटर्स (या गतिशील सरणी!) से अलग-अलग प्रकार हैं, क्योंकि यह ठीक है सी है।

This आकार के व्यवहार पर एक सभ्य संदर्भ प्रतीत होता है।

1

सरणी सूचक नहीं है। पॉइंटर एक मेमोरी लोकेशन पर इशारा करते हुए एक चर है जबकि सरणी अनुक्रमित मेमोरी

1

इसकी वजह

  1. string1 सूचक है, जहां सूचक सन्निहित वर्ण है & अपने अपरिवर्तनीय रखती है।
  2. स्ट्रिंग 2 वह स्थान है जहां आपके वर्ण बैठते हैं।

मूल रूप से सी कंपाइलर इन 2 अलग-अलग तरीकों से दोहराता है। http://c-faq.com/aryptr/aryptr2.html खूबसूरती से समझाया गया।

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