एक मूल्य के साथ पूरे 2D सरणी की शुरुआत


82

निम्नलिखित घोषणा के साथ

मुझे सभी शून्य के साथ सरणी मिलती है, लेकिन निम्नलिखित के साथ

मैं सभी एक मूल्य के साथ सरणी नहीं मिलता है। डिफ़ॉल्ट मान अभी भी 0 है।

यह व्यवहार क्यों है और मैं सभी 1 के साथ कैसे आरंभ कर सकता हूं?

संपादित करें: मैंने अभी-अभी यह समझा है कि memset1 के रूप में मान के साथ प्रयोग करने पर, प्रत्येक बाइट को 1 के रूप में सेट किया जाएगा और इसलिए प्रत्येक ऐरे सेल का वास्तविक मान 1 नहीं होगा 16843009। मैं इसे 1 पर कैसे सेट करूं?


1
@ckruse: सवाल नहीं है कैसे , यह क्यों
मसूद

@ एम.एम. उत्तर मैं दिए गए धागे में दिया गया है।
crruse

समस्या वास्तव में why and howदोनों थी। :)
क्राकेन

@Kraken आपके संपादन का प्रश्न संभवतः इस से अलग प्रश्न के रूप में पोस्ट किया जाना चाहिए।
लुंडिन

1
@Kraken वास्तव में मुझे वह प्रश्न यहाँ मिला । मैं अपने उत्तर (निश्चित रूप से) में सुझाव के अनुसार करने की सलाह दूंगा और जीसीसी एक्सटेंशन पर निर्भर नहीं होना चाहिए।
लुंडिन

जवाबों:


126

आपको यह व्यवहार मिलता है, क्योंकि int array [ROW][COLUMN] = {1};इसका अर्थ "सभी वस्तुओं को एक पर सेट करना" नहीं है। मुझे यह समझाने की कोशिश करें कि यह कदम से कदम कैसे काम करता है।

अपने सरणी को आरम्भ करने का स्पष्ट, अति स्पष्ट तरीका इस प्रकार होगा:

हालाँकि, सी आपको कुछ वस्तुओं को एक सरणी (या संरचना / संघ) में छोड़ने की अनुमति देता है। आप उदाहरण के लिए लिख सकते हैं:

इसका मतलब है, पहले तत्वों को 1 और 2 से आरंभ करें, और बाकी तत्व "जैसे कि उनके पास स्थिर भंडारण अवधि थी"। सी में एक नियम है, जिसमें कहा गया है कि स्थिर भंडारण अवधि की सभी वस्तुएं, जो प्रोग्रामर द्वारा स्पष्ट रूप से आरंभिक नहीं हैं, को शून्य पर सेट किया जाना चाहिए।

इसलिए उपर्युक्त उदाहरण में, पहली पंक्ति 1,2 पर सेट हो जाती है और अगली 0,0 के लिए, क्योंकि हमने उन्हें कोई स्पष्ट मान नहीं दिया है।

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

हालांकि यह खराब शैली है, लेकिन इसे पढ़ना और समझना कठिन है। लेकिन यह नियम सुविधाजनक है, क्योंकि यह हमें लिखने की अनुमति देता है

जिसका अर्थ है: "पहली पंक्ति में बहुत पहले कॉलम को 0 पर प्रारंभ करें, और अन्य सभी आइटम जैसे कि उनके पास स्थिर भंडारण अवधि थी, अर्थात उन्हें शून्य पर सेट करें।"

इसलिए, यदि आप प्रयास करते हैं

इसका अर्थ है "पहली पंक्ति में बहुत पहले कॉलम को 1 में आरंभीकृत करें और अन्य सभी वस्तुओं को शून्य पर सेट करें"।


2
उस के लिए धन्यवाद, कुछ भी मैं पूरे सरणी को 1 के साथ जोड़ने के लिए कर सकता हूं? मेरी पंक्तियों और स्तंभों पर विचार करना सैकड़ों आकार का है?
क्राकेन

1
@ मैक्रो ट्रिक के साथ। इसे देखें
लंडिन

क्या यह सिर्फ मैं हूं या क्या आपको कोष्ठक के दूसरे सेट की आवश्यकता है:int array [ROW][COLUMN] = {{0}};
user1794469

@ user1794469 नहीं, आप नहीं।
लुंडिन

1
@ user1794469 हाँ, और यह अच्छा है, क्योंकि ज्यादातर मामलों में लंघन लंघन बुरा अभ्यास है। लेकिन संकलक नहीं करता है एक नैदानिक देने के लिए। इस मामले के लिए अच्छे / बुरे व्यवहार के बारे में, इस सवाल का मेरा जवाब देखें ।
लुंडिन

40

यदि आप सरणी को इनिशियलाइज़ करना चाहते हैं -1तो आप निम्न का उपयोग कर सकते हैं,

लेकिन यह केवल 0और -1केवल काम करेगा


17
"आकार (सरणी [0] [0]] * पंक्ति * गिनती" के बजाय "साइज़ोफ़ (सरणी)" का उपयोग करना आसान है।
व्लादिस्लाव सवेंको

यह किसी भी निरंतर बाइट के लिए काम करता है, हालांकि यह मेरे लिए स्पष्ट नहीं है कि इसके अलावा क्या उपयोगी होगा 0000और1111
user1794469

5
शामिल करने के लिए की जरूरत <cstring>C ++
MTK

12

यह केवल पहले तत्व को शुरुआती करता है। बाकी सब कुछ 0 मिलता है।

पहले उदाहरण में, आप वही कर रहे हैं - पहले तत्व को 0 में इनिशियलाइज़ कर रहा है, और बाकी को 0 में डिफॉल्ट करता है।

कारण सीधा है: एक सरणी के लिए, कंपाइलर आपके द्वारा निर्दिष्ट हर मूल्य को 0 से निर्दिष्ट नहीं करेगा।

एक charसरणी के साथ आप memsetप्रत्येक बाइट को सेट करने के लिए उपयोग कर सकते हैं , लेकिन यह आम तौर पर एक intसरणी के साथ काम नहीं करेगा (हालांकि यह 0 के लिए ठीक है)।

एक सामान्य forलूप इसे जल्दी करेगा:

या संभवतः तेज (संकलक के आधार पर)


1
@Kraken - ऐसा नहीं है - 0केवल पहले मूल्य को भी इनिशियलाइज़ करता है। यह 0डिफ़ॉल्ट रूप से शेष सभी को इनिशियलाइज़ करता है ।
टेकपिक

@ EricPostpischil तो, यह 1 के साथ सभी बाइट्स सेट करता है, इसलिए अगर मैं 32 बिट पूर्णांक पर विचार करता हूं, तो यदि मेरा valueक्षेत्र memset1 है तो मैट्रिक्स में वास्तविक मान 1 नहीं होगा 2^0 + 2^8 + 2^16 + 2^24?
क्राकेन

@Kraken: अनिवार्य रूप से, हाँ। memsetप्रत्येक बाइट को उसके गंतव्य में दिए गए मान पर सेट करता है, जो intकि 1 को सेट करने के लिए काम नहीं करेगा। एक से memsetअधिक-बाइट ऑब्जेक्ट के मूल्यों को सेट करने के लिए उपयोग नहीं किया जा सकता है जब तक कि आप प्रत्येक बाइट को उसी मान पर सेट न करें।
एरिक पोस्टपिसिल

@ EricPostpischil तो मैन्युअल रूप से प्रत्येक को इनिशियलाइज़ करने के अलावा इसे करने का कोई तरीका नहीं है? मेरी पंक्तियों और कॉलमों को ध्यान में रखते हुए भी कुछ हजारों में हैं?
क्राकेन

@Kraken मैंने एक स्पष्टीकरण पोस्ट किया है क्यों {1} काम नहीं करता है। और वास्तव में मैनुअल इनिशियलाइजेशन के अलावा और कोई रास्ता नहीं है। आपको हजारों की संख्या टाइप करने की आवश्यकता नहीं है, हालांकि, मैक्रो ट्रिक्स हैं, लेकिन यह शायद एक और प्रश्न का विषय है।
लुंडिन

8

ध्यान दें कि जीसीसी के पास नामित प्रारंभिक संकेतन का विस्तार है जो संदर्भ के लिए बहुत उपयोगी है। यह clangबिना टिप्पणी के भी अनुमति दी जाती है (भाग में क्योंकि यह जीसीसी के साथ संगत होने की कोशिश करता है)।

विस्तार संकेतन आपको ...निम्नलिखित मानों के साथ आरंभ करने के लिए तत्वों की एक श्रृंखला को नामित करने के लिए उपयोग करने की अनुमति देता है । उदाहरण के लिए:

आउटपुट है, आश्चर्यजनक रूप से:

ध्यान दें कि फोरट्रान 66 (फोरट्रान IV) में सरणियों के लिए इनिशियलाइज़र के लिए रिपीट काउंट थे; यह हमेशा मुझे अजीब लगता है कि सी उन्हें तब नहीं मिली जब नामित शुरुआती भाषा में जोड़े गए थे। और पास्कल 0..90 से 9 समावेशी सीमा को नामित करने के लिए संकेतन का उपयोग करता है , लेकिन C ..एक टोकन के रूप में उपयोग नहीं करता है , इसलिए यह आश्चर्य की बात नहीं है कि इसका उपयोग नहीं किया गया था।

ध्यान दें कि ...अंकन के चारों ओर रिक्त स्थान अनिवार्य रूप से अनिवार्य हैं; यदि वे संख्याओं से जुड़े होते हैं, तो संख्या को एक अस्थायी बिंदु संख्या के रूप में व्याख्या की जाती है। उदाहरण के लिए, 0...9के रूप में tokenized किया जाएगा 0., ., .9, और चल बिन्दु संख्या सरणी सबस्क्रिप्ट के रूप में अनुमति नहीं है। नामित स्थिरांक के साथ, ...ROW-1परेशानी का कारण नहीं होगा, लेकिन सुरक्षित आदतों में शामिल होना बेहतर है।


Addenda:

मैंने ध्यान दिया कि GCC 7.3.0 को अस्वीकार करने में:

जहाँ अदिश आरम्भक 1( error: braces around scalar initializer [-Werror]) के चारों ओर ब्रेसिज़ का एक अतिरिक्त सेट है । मुझे यकीन नहीं है कि यह सही है कि आप सामान्य रूप से एक स्केलर के चारों ओर ब्रेसिज़ निर्दिष्ट कर सकते हैं int a = { 1 };, जो स्पष्ट रूप से मानक द्वारा अनुमत है। मुझे यकीन नहीं है कि यह गलत है, या तो।

मुझे यह भी आश्चर्य है कि अगर एक बेहतर अंकन होगा [0]...[9]- जो कि असंदिग्ध है, किसी अन्य मान्य वाक्यविन्यास के साथ भ्रमित नहीं किया जा सकता है, और अस्थायी बिंदु संख्याओं के साथ भ्रम से बचा जाता है।

शायद मानक समिति इस पर विचार करेगी?


7

शून्य विधि के साथ 2d सरणी शुरू करने के लिए नीचे दी गई विधि का उपयोग करें: int arr[n][m] = {};

नोट : उपरोक्त विधि केवल 0 से आरंभ करने के लिए काम करेगी;



हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.