2008-09-18 14 views
238

जब {0} किसी ऑब्जेक्ट को प्रारंभ करने के लिए उपयोग किया जाता है, तो इसका क्या अर्थ है? मुझे कहीं भी {0} पर कोई संदर्भ नहीं मिल रहा है, और घुंघराले ब्रेसिज़ की वजह से Google खोज उपयोगी नहीं हैं।किसी ऑब्जेक्ट को प्रारंभ करते समय {0} का क्या अर्थ है?

उदाहरण कोड:

SHELLEXECUTEINFO sexi = {0}; // what does this do? 
sexi.cbSize = sizeof(SHELLEXECUTEINFO); 
sexi.hwnd = NULL; 
sexi.fMask = SEE_MASK_NOCLOSEPROCESS; 
sexi.lpFile = lpFile.c_str(); 
sexi.lpParameters = args; 
sexi.nShow = nShow; 

if(ShellExecuteEx(&sexi)) 
{ 
    DWORD wait = WaitForSingleObject(sexi.hProcess, INFINITE); 
    if(wait == WAIT_OBJECT_0) 
     GetExitCodeProcess(sexi.hProcess, &returnCode); 
} 

इसके बिना, ऊपर कोड क्रम पर क्रैश हो जाएगा।

उत्तर

292

यहां क्या हो रहा है उसे कुल प्रारंभिक कहा जाता है।

एक कुल एक सरणी या कोई उपयोगकर्ता के घोषित कंस्ट्रक्टर्स के साथ एक वर्ग, कोई निजी या संरक्षित गैर स्थिर डेटा सदस्यों है: यहाँ (संक्षिप्त) आईएसओ कल्पना की धारा 8.5.1 से एक समग्र की परिभाषा है , कोई आधार वर्ग नहीं, और कोई वर्चुअल फ़ंक्शन नहीं।

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

यहाँ कल्पना से प्रासंगिक उद्धरण है:

यदि सूची में कम initializers से वहाँ कुल में सदस्य हैं कर रहे हैं, तो प्रत्येक सदस्य नहीं स्पष्ट रूप से प्रारंभ डिफ़ॉल्ट-प्रारंभ किया जाएगा। उदाहरण:

struct S { int a; char* b; int c; }; 
S ss = { 1, "asdf" }; 

initializes "asdf" साथ 1 साथ ss.a, ss.b, और प्रपत्र int() के अभिव्यक्ति के मूल्य के साथ ss.c, कि है, 0

आपके पास इस विषय here

+14

उत्कृष्ट प्रतिक्रिया। बस यह जोड़ना चाहता था कि {0} के साथ कुल मिलाकर प्रारंभ करना ही {} के साथ शुरू करना जैसा ही है।शायद पूर्व यह स्पष्ट करता है कि अंतर्निहित प्रकार शून्य हो जाते हैं। –

+6

कुछ कंपाइलर्स {} पर चकित होते हैं, यही कारण है कि {0} – Branan

+9

उपयोग नहीं किया जाता है .. सी ++ में, यदि पहला सदस्य शून्य-निर्मित नहीं हो सकता है तो {0} काम नहीं करेगा। पूर्व: संरचना ए {बी बी; int i; चार सी; }; संरचना बी {बी(); बी (स्ट्रिंग); }; ए = {}; // इस कथन को 'ए = {0}' के रूप में पुनः लिखा नहीं जा सकता है। – Aaron

3

यह समय हो गया है मैं ग में काम पर पूरा कल्पना पा सकते हैं/C++ लेकिन IIRC, एक ही शॉर्टकट के रूप में अच्छी तरह से सरणियों के लिए इस्तेमाल किया जा सकता है।

7

मैं स्ट्रिंग्स को प्रारंभ करने के लिए इसका उपयोग भी करता हूं।

char mytext[100] = {0}; 
+5

हालांकि, अगर मायटेक्स्ट को स्ट्रिंग का उपयोग किया जा रहा है, तो char mytext [100]; mytext [0] = '\ 0'; एक खाली स्ट्रिंग देने का एक ही प्रभाव होगा, लेकिन कार्यान्वयन केवल पहले बाइट को शून्य करने का कारण बनता है। – Chris

+0

@ क्रिस: मैंने अक्सर कामना की है कि आंशिक ऑब्जेक्ट प्रारंभिकरण के लिए एक वाक्यविन्यास था। X घोषित करने और आरंभ करने में सक्षम होने के नाते, फिर y के साथ ऐसा करें, फिर z, x, y, और z घोषित करने से बहुत अच्छा है, और उसके बाद x, y, और z प्रारंभ करें, लेकिन केवल 100 बाइट प्रारंभ करें वास्तव में शुरुआत की जरूरत है बल्कि अपर्याप्त लगता है। – supercat

84

इस बात से अवगत होना एक बात यह है कि यह तकनीक पैडिंग बाइट को शून्य पर सेट नहीं करेगी। उदाहरण के लिए:

struct foo 
{ 
    char c; 
    int i; 
}; 

foo a = {0}; 

नहीं के रूप में ही है:

foo a; 
memset(&a,0,sizeof(a)); 

पहले मामले में, ग के बीच पैड बाइट्स और मैं अप्रारंभीकृत हैं। आप परवाह क्यों करेंगे? खैर, अगर आप इस डेटा को डिस्क पर सहेज रहे हैं या इसे नेटवर्क पर भेज रहे हैं या जो कुछ भी हो, तो आपको सुरक्षा समस्या हो सकती है।

+13

बेशक, यह केवल एक सुरक्षा समस्या है यदि आप 'लिखते हैं (एफ, और ए, आकार (ए))', जो विभिन्न प्रोसेसर/कंपाइलरों पर विभिन्न फ़ाइल एन्कोडिंग का उत्पादन कर सकता है। अच्छी तरह से स्वरूपित आउटपुट स्मृति के बिना सुरक्षित होगा। – Aaron

+3

इसके अलावा, यदि आप नेटवर्क पर सामान भेज रहे हैं तो आप हमेशा संरेखण को पैक करने के लिए सेट करेंगे। इस तरह आप जितना संभव हो उतना अतिरिक्त पैडिंग बाइट प्राप्त करते हैं। –

+0

एक सूचना रिसाव से बचने के बारे में उत्कृष्ट बिंदु ... – paxos1977

18

ध्यान दें कि एक खाली कुल प्रारंभकर्ता भी काम करता है:

SHELLEXECUTEINFO sexi = {}; 
char mytext[100] = {}; 
11
क्यों ShellExecuteEx() क्रैश हो रहा है

जवाब में: अपने SHELLEXECUTEINFO "sexi" struct कई सदस्य हैं और आप केवल उनमें से कुछ आरंभ कर रहे हैं।

उदाहरण के लिए, सदस्य sexi.lpDirectory कहीं भी इंगित कर सकता है, लेकिन ShellExecuteEx() अभी भी इसका उपयोग करने का प्रयास करेगा, इसलिए आपको स्मृति पहुंच उल्लंघन मिलेगा।

जब आप लाइन में शामिल हैं:

SHELLEXECUTEINFO sexi = {0}; 
अपने संरचना सेटअप के बाकी से पहले

, आप सभी संरचना के सदस्यों को शून्य करने के लिए इससे पहले कि आप विशिष्ट लोगों में आपकी रुचि है प्रारंभ संकलक बता रहे हैं ShellExecuteEx() जानता है कि अगर sexi.lpDirectory शून्य है, तो इसे अनदेखा करना चाहिए।

2

मैं हमेशा आश्चर्य होता है, क्यों आप कुछ तरह

struct foo bar = { 0 }; 

यहाँ एक परीक्षण का मामला समझाने के लिए किया जाता है का उपयोग करना चाहिए:

check.c

struct f { 
    int x; 
    char a; 
} my_zero_struct; 

int main(void) 
{ 
    return my_zero_struct.x; 
} 

मैं gcc -O2 -o check check.c साथ संकलन और फिर readelf -s check | sort -k 2 के साथ प्रतीक तालिका आउटपुट (यह x64 सिस्टम पर ubuntu 12.04.2 पर gcc 4.6.3 के साथ है)। अंश:

59: 0000000000601018  0 NOTYPE GLOBAL DEFAULT ABS __bss_start 
48: 0000000000601018  0 NOTYPE GLOBAL DEFAULT ABS _edata 
25: 0000000000601018  0 SECTION LOCAL DEFAULT 25 
33: 0000000000601018  1 OBJECT LOCAL DEFAULT 25 completed.6531 
34: 0000000000601020  8 OBJECT LOCAL DEFAULT 25 dtor_idx.6533 
62: 0000000000601028  8 OBJECT GLOBAL DEFAULT 25 my_zero_struct 
57: 0000000000601030  0 NOTYPE GLOBAL DEFAULT ABS _end 

यहाँ महत्वपूर्ण हिस्सा है, my_zero_struct__bss_start के बाद है। एक सी प्रोग्राम में ".bss" अनुभाग स्मृति का वह भाग है जो शून्य परmain से पहले wikipedia on .bss देखा जाता है।

आप के लिए ऊपर दिए गए कोड को बदलते हैं:

} my_zero_struct = { 0 }; 

फिर जिसके परिणामस्वरूप "जाँच" निष्पादन योग्य लग रहा है बिल्कुल ही कम से कम ubuntu 12.04.2 पर जीसीसी 4.6.3 संकलक के साथ; my_zero_struct अभी भी .bss सेक्शन में है और इस प्रकार main से पहले इसे स्वचालित रूप से शून्य में प्रारंभ किया जाएगा।

टिप्पणियों में संकेत, कि memset "पूर्ण" संरचना शुरू हो सकती है, यह भी सुधार नहीं है, क्योंकि .bss अनुभाग पूरी तरह से साफ़ हो गया है जिसका अर्थ है कि "पूर्ण" संरचना शून्य पर सेट है।

यह हो सकता है कि सी भाषा मानक इनमें से किसी का भी उल्लेख नहीं करता है, लेकिन असली दुनिया में सी संकलक मैंने कभी अलग व्यवहार नहीं देखा है।

+0

मैं कम से कम एमएसवीसी हमेशा ऐसा नहीं करता ... –

-4

{0} एक गुमनाम सरणी यह 0 के साथ सरणी में से एक या सभी तत्वों को प्रारंभ लिए किया जाता है के रूप में 0.

अपने तत्व से युक्त है।

उदा। int arr [8] = {0};

इस मामले में सभी आगमन के तत्वों के रूप 0.

+4

'{0}' अज्ञात सरणी नहीं है। यह एक अभिव्यक्ति भी नहीं है। यह एक प्रारंभिक है। –

7

{0} प्रारंभ हो जाएगा किसी भी (पूरा वस्तु) के लिए एक वैध प्रारंभकर्ता टाइप करें, दोनों C और C++ में है। यह एक सामान्य मुहावरे है जिसे किसी ऑब्जेक्ट को शून्य पर प्रारंभ करने के लिए उपयोग किया जाता है (यह देखने के लिए पढ़ें कि इसका क्या अर्थ है)।

स्केलर प्रकारों (अंकगणित और सूचक प्रकार) के लिए, ब्रेसिज़ अनावश्यक हैं, लेकिन उन्हें स्पष्ट रूप से अनुमति दी जाती है।

एक अदिश के लिए प्रारंभकर्ता एक भी अभिव्यक्ति, वैकल्पिक रूप से ब्रेसिज़ में संलग्न किया जाएगा: आईएसओ सी मानक, खंड 6.7.9 के N1570 draft का हवाला देते हुए।

यह (फ्लोटिंग प्वाइंट के लिए 0 पूर्णांकों के लिए, 0.0, संकेत के लिए एक नल पॉइंटर) शून्य के वस्तु initializes।

गैर अदिश प्रकार (संरचनाओं, सरणियों, यूनियनों) के लिए, {0} निर्दिष्ट करता है कि पहले वस्तु का तत्व शून्य करने के लिए आरंभ नहीं हो जाता। संरचनाओं, संरचनाओं के सरणी, और इसी तरह की संरचनाओं के लिए, यह पुनरावर्ती रूप से लागू होता है, इसलिए पहला स्केलर तत्व शून्य पर सेट होता है, जैसा कि प्रकार के लिए उपयुक्त है। किसी भी प्रारंभकर्ता के रूप में, निर्दिष्ट नहीं किए गए तत्व शून्य पर सेट हैं।

इंटरमीडिएट ब्रेसिज़ ({, }) छोड़ा जा सकता है; उदाहरण के लिए इन दोनों वैध और बराबर हैं:

int arr[2][2] = { { 1, 2 }, {3, 4} }; 

int arr[2][2] = { 1, 2, 3, 4 }; 

और इसी कारण आप, लिखने के लिए एक प्रकार जिसका पहला तत्व गैर अदिश है उदाहरण के लिए, { { 0 } } के लिए नहीं है।

तो यह:

some_type obj = { 0 }; 

शून्य करने के लिए obj आरंभ की एक आशुलिपि तरीका है, जिसका अर्थ है कि obj से प्रत्येक अदिश उप वस्तु 0 के लिए निर्धारित है अगर यह एक पूर्णांक, 0.0 अगर यह है फ्लोटिंग प्वाइंट है, या एक शून्य सूचक अगर यह एक सूचक है।

नियम सी ++ के समान हैं।

अपने विशेष मामले में, जब से तुम sexi.cbSize को मान निर्दिष्ट कर रहे हैं और बहुत आगे है, यह स्पष्ट है कि SHELLEXECUTEINFO एक struct या वर्ग प्रकार है (या शायद एक संघ है, लेकिन शायद नहीं), तो यह सब नहीं लागू होता है, लेकिन जैसा कि मैंने कहा { 0 } एक आम मुहावरे है जिसका उपयोग अधिक सामान्य परिस्थितियों में किया जा सकता है।

यह (आवश्यक रूप से) memset का उपयोग करने के बराबर है, ऑब्जेक्ट के सभी बिट्स-शून्य पर ऑब्जेक्ट का प्रतिनिधित्व सेट करने के लिए। न तो फ्लोटिंग-पॉइंट 0.0 और न ही शून्य सूचक को सभी बिट्स-शून्य के रूप में दर्शाया जाता है, और { 0 } प्रारंभकर्ता किसी भी विशेष मूल्य पर पैडिंग बाइट सेट नहीं करता है। अधिकांश प्रणालियों पर, हालांकि, यह एक ही प्रभाव होने की संभावना है।

+1

सी ++ में, '{0}' किसी ऑब्जेक्ट के लिए वैध प्रारंभकर्ता नहीं है जिसमें कोई कन्स्ट्रक्टर '0' स्वीकार नहीं करता है; न ही कुल के लिए जिसका पहला तत्व इस तरह है (या कोई तत्व नहीं है) –

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