ऐसा करना निश्चित रूप से मान्य है:

char src[] = "Allie has a cat.";
char buff[20];
strcpy(buff, src);
printf("%s\n", buff);

या यह:

printf("Allie has a cat.\n");

लेकिन, क्या इसके लिए उपरोक्त कोड को छोटा करना मान्य है?

char buff[20];
strcpy(buff, "Allie has a cat.");
printf("%s\n", buff);

या लिखने के लिए:

printf("%s", "Allie has a cat.");

कारण मैं पूछ रहा हूं कि सी स्ट्रिंग अक्षर में AFAIK चरित्र सरणी की तुलना में कुछ अलग जानवर हैं, और दोनों उदाहरण काम कर रहे हैं (ideone#1, ideone#2), मुझे लगता है कि जब सीआई की बात आती है तो ऐसा कुछ न करें जो मुझे लगता है कि केवल मान्य होना चाहिए या ऐसा लगता है कि इस भाषा में कितने नुकसान हैं और इस भाषा में एक निर्माण लिखना कितना आसान है जो निर्दोष दिखता है लेकिन फिर भी यूबी है।

3
user4385532 27 मई 2017, 00:05
5
सभी उदाहरण ठीक काम करना चाहिए। स्ट्रिंग अक्षर केवल char केवल पढ़ने योग्य स्मृति में सरणी हैं। बीटीडब्ल्यू, पहले स्निपेट में कोई स्ट्रिंग अक्षर नहीं है।
 – 
Eugene Sh.
27 मई 2017, 00:07
2
@EugeneSh .: क्या कोड संपादित किया गया था? पहले स्निपेट में एक स्ट्रिंग शाब्दिक "Allie has a cat." है। (इसका उपयोग src को इनिशियलाइज़ करने के अलावा नहीं किया जाता है।)
 – 
Keith Thompson
27 मई 2017, 00:43
सही है। यह सी मानक के अनुसार स्ट्रिंग शाब्दिक है (" डबल-कोट्स में संलग्न शून्य या अधिक मल्टीबाइट वर्णों का अनुक्रम"), लेकिन "केवल-पढ़ने के लिए चार सरणी मेमोरी में एक पता होने के अर्थ में नहीं है" ", जिसे पुनरावृत्त किया जा सकता है या ओपी का पता लिया जा सकता है, के बारे में चिंतित है।
 – 
Eugene Sh.
27 मई 2017, 00:51
@ यूजीनश। विवरण: "स्ट्रिंग अक्षर केवल पढ़ने के लिए स्मृति में केवल चार सरणी हैं" -> स्ट्रिंग अक्षर केवल-पढ़ने के लिए स्मृति में संग्रहीत किया जा सकता है या नहीं। स्ट्रिंग अक्षर के डेटा को बदलने का प्रयास "काम" कर सकता है, ऐसा नहीं हो सकता है, यह यूबी है,
 – 
chux - Reinstate Monica
27 मई 2017, 06:23

2 जवाब

यह बिल्कुल मान्य है। स्ट्रिंग अक्षर वर्ण सरणी हैं:

6.4.5 स्ट्रिंग अक्षर

[...]

  1. अनुवाद चरण 7 में, प्रत्येक मल्टीबाइट में एक बाइट या शून्य मान का कोड जोड़ा जाता है वर्ण अनुक्रम जो एक स्ट्रिंग शाब्दिक या शाब्दिक से उत्पन्न होता है। मल्टीबाइट कैरेक्टर अनुक्रम का उपयोग तब स्थिर भंडारण अवधि और लंबाई की एक सरणी को प्रारंभ करने के लिए किया जाता है अनुक्रम रखने के लिए पर्याप्त है। वर्ण स्ट्रिंग अक्षर के लिए, सरणी तत्वों में है char टाइप करें, और मल्टीबाइट कैरेक्टर के अलग-अलग बाइट्स के साथ इनिशियलाइज़ होते हैं अनुक्रम [...]

  2. यह निर्दिष्ट नहीं है कि क्या ये सरणियाँ अलग हैं, बशर्ते उनके तत्वों में उपयुक्त मूल्य। यदि प्रोग्राम ऐसी सरणी को संशोधित करने का प्रयास करता है, तो व्यवहार है अपरिभाषित।

(स्रोत: आईएसओ 9899:1999 ("सी99"))

तो कुछ

strcpy(buff, "Allie has a cat.");

प्रभावी रूप से बराबर है

static char __s0[] = "Allie has a cat.";
strcpy(buff, __s0);

(एक स्ट्रिंग अक्षर को संशोधित करने के अलावा अपरिभाषित व्यवहार है)।

6
melpomene 27 मई 2017, 00:14
1
अपने जवाब के लिए धन्यवाद! हालांकि, एक नाइटपिक: AFAIK लेखन static char __s0[] यूबी है, क्योंकि पहचानकर्ता एक से शुरू होते हैं डबल अंडरस्कोर आरक्षित हैं और उन्हें यूबी घोषित कर रहे हैं। तो, ये दो स्निपेट प्रभावी रूप से समकक्ष नहीं हैं, क्योंकि एक यूबी है और दूसरा नहीं है :)
 – 
gaazkam
27 मई 2017, 00:19
मैं यह नहीं कहूंगा कि दो स्निपेट बराबर हैं। ठीक है, अर्थ की दृष्टि से हो सकता है, यदि कोई अन्य कोड आसपास नहीं है, लेकिन पहले एक में __s0 आरंभिक .data अनुभाग में जाएगा, जबकि दूसरे में शाब्दिक संभवतः .text में बैठेगा। या .rodata अनुभाग।
 – 
Eugene Sh.
27 मई 2017, 00:20
8
मैं यह दिखाने की कोशिश कर रहा हूं कि पर्दे के पीछे कार्यान्वयन क्या कर रहा है। इसलिए मेरा कोड कार्यान्वयन के लिए आरक्षित पहचानकर्ता का उपयोग करता है।
 – 
melpomene
27 मई 2017, 00:20
3
जहां तक ​​​​मैं कह सकता हूं, मानक वास्तव में यह नहीं कहता कि स्ट्रिंग अक्षर का मान क्या है। यह कहता है कि अनुक्रम का उपयोग स्थिर सरणी को प्रारंभ करने के लिए किया जाता है, लेकिन यह नहीं कहता कि शाब्दिक उस सरणी को संदर्भित करता है। मुझे लगता है कि इरादा पर्याप्त रूप से स्पष्ट है। (यह एक भाषा-वकील नाइटपिक है, वास्तविक शिकायत नहीं।)
 – 
Keith Thompson
27 मई 2017, 00:49

ऐतिहासिक कारणों से, स्ट्रिंग अक्षर को const char के बजाय char की सरणी के रूप में घोषित किया जाता है, लेकिन मानक न तो गारंटी देता है कि उन्हें संशोधित किया जा सकता है और न ही वे नहीं कर सकते हैं। इसका कारण यह है कि 1989 तक पहले से ही कार्यान्वयन थे जो इसे दोनों तरीकों से करते थे। व्यवहार में, आज ही उन्हें const char[] के रूप में मानें और उन्हें कभी भी संशोधित करने का प्रयास न करें।

कंपाइलर्स को एक ही मेमोरी को कई कैरेक्टर स्थिरांक के लिए फिर से उपयोग करने की अनुमति है, इसलिए यह न मानें कि समान स्ट्रिंग्स या सबस्ट्रिंग ओवरलैप होंगे या नहीं।

पता लेना, उस पर पुनरावृत्ति करना और सामग्री को टर्मिनेटिंग नल तक पढ़ना सभी पूरी तरह से सुरक्षित हैं।

परिशिष्ट भाग

मानक के शब्द, जिसे मेलपोमीन ने अपने उत्तर में उद्धृत किया, का कहना है कि एक चरित्र स्थिरांक को संशोधित करना अपरिभाषित व्यवहार है। चूँकि इसने टिप्पणियों में चर्चा को प्रेरित किया, यहाँ इसका क्या अर्थ है।

यदि आप एक स्ट्रिंग अक्षर में एक चरित्र को संशोधित करते हैं, तो आप किसी भी गारंटी को जब्त कर लेते हैं जो मानक आपको देता है कि प्रोग्राम क्या कर सकता है। कंपाइलर को कुछ भी करने के लिए एएनएसआई और आईएसओ का आशीर्वाद प्राप्त है। इसलिए, यदि आप char hello[] = "hello"; और फिर array[4] = 'p'; घोषित करते हैं, तो यहां कुछ चीजें हो सकती हैं:

  • संकलक आपको एक त्रुटि दे सकता है और कार्यक्रम को अस्वीकार कर सकता है।
  • puts("hello"); hellp प्रिंट कर सकता है।
  • puts("Say hello"); Say hellp प्रिंट कर सकता है।
  • puts(hello); hello प्रिंट कर सकता है।
  • puts(hello); hellp प्रिंट कर सकता है।
  • अनुकूलक जो करता है उसके आधार पर या तो hello या "hello" में असंगत रूप से hello या hellp हो सकते हैं।
  • प्रोग्राम लाइन array[4] = 'p'; पर क्रैश हो सकता है
  • आपके कार्यक्रमों को संकलित करने वाला सुपरइंटेलिजेंट एआई तय कर सकता है कि मानवीय मूर्खता मिशन को खतरे में डाल रही है और आपको मारने की कोशिश कर रही है।

इनमें से प्रत्येक व्यवहार के उदाहरण हैं, हालांकि वह अंतिम व्यवहार किसी फिल्म से हो सकता है।

3
Davislor 27 मई 2017, 01:29
1
यह कहने के लिए बालों को बहुत बारीक रूप से विभाजित कर रहा है कि मानक गारंटी नहीं देता है कि स्ट्रिंग अक्षर को संशोधित नहीं किया जा सकता है। यह निश्चित रूप से करता है कि किसी को संशोधित करने का कोई भी प्रयास अपरिभाषित व्यवहार उत्पन्न करता है।
 – 
John Bollinger
27 मई 2017, 00:16
1
यह करना सुरक्षित नहीं है, लेकिन मेरा मतलब है कि आपको इस बात की कोई गारंटी नहीं है कि वर्ण स्थिरांक केवल-पढ़ने के लिए स्मृति में है या कोड का कोई अन्य भाग आपके साथ ऐसा नहीं कर सकता है। व्यवहार में, मुझे नहीं लगता कि किसी ने दशकों में इसे उद्देश्य से किया है।
 – 
Davislor
27 मई 2017, 00:20
क्या करना सुरक्षित नहीं है, क्षमा करें?
 – 
Eugene Sh.
27 मई 2017, 00:24
ठीक है, लेकिन यह विशेष रूप से विशिष्ट नहीं है। उस अर्थ में, मानक गारंटी के साथ ऐसा कुछ भी नहीं है जो आप नहीं कर सकते।
 – 
John Bollinger
27 मई 2017, 00:24
1
@ जॉन बोलिंगर: और अपरिभाषित व्यवहार सचमुच कुछ भी कर सकता है। एक अनुरूप कार्यान्वयन में यह कोड हो सकता है: char *s = "hello"; s[0] = 'H'; स्ट्रिंग को "Hello" पर सेट करें। (और tcc ठीक वैसा ही करता है, हालांकि मुझे नहीं लगता कि यह पूरी तरह से अनुरूप है।)
 – 
Keith Thompson
27 मई 2017, 00:45