किसी वस्तु को शुरू करते समय {0} का क्या अर्थ है?


252

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

उदाहरण कोड:

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);
}

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

जवाबों:


302

यहां जो कुछ हो रहा है उसे एग्रीगेट इनिशियलाइजेशन कहा जाता है। यहाँ ISO युक्ति की धारा 8.5.1 से एक समुच्चय की संक्षिप्त (संक्षिप्त) परिभाषा है:

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

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

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

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

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

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

आप इस विषय पर पूरा कल्पना पा सकते हैं यहाँ


15
बहुत बढ़िया प्रतिक्रिया। बस यह जोड़ना चाहता था कि {0} के साथ एक एग्रीगेट बनाना केवल {} के साथ इसे इनिशियलाइज़ करना है। शायद पूर्व यह अधिक स्पष्ट करता है कि अंतर्निहित प्रकार शून्य हो जाते हैं।
जेम्स हॉपकिन

7
कुछ संकलक {} पर चोक करते हैं, इसीलिए {0} का उपयोग किया जाता है
ब्रानन

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

25
@Branan, ऐसा इसलिए है क्योंकि C "{}" मान्य नहीं है। C ++ में यह है। @ don.neufeld, यह C ++ 03 (डिफ़ॉल्ट-आरंभिक -> मूल्य-आरंभीकृत) के साथ बदल गया है। उद्धरण C ++ 98 मानक का हवाला देते हुए, ध्यान में रखता है।
जोहान्स शाउब -

3
तो, क्या यह ZeroMemory () (VC ++ में) का उपयोग करने की आवश्यकता को प्रतिस्थापित करता है?
रे

89

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

struct foo
{
    char c;
    int  i;
};

foo a = {0};

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

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

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


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

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

18
यह ध्यान दिया जाना चाहिए कि हालांकि कल्पना को पैडिंग को आरंभीकृत करने की आवश्यकता नहीं है, किसी भी समझदार संकलक को, क्योंकि इसे "इर्द-गिर्द" शुरू करने के लिए केवल समय लगता है।
टॉमस

4
मैं "नहीं है" शब्दों के उपयोग के साथ समस्या लेना चाहता हूं। पैडिंग बाइट्स कार्यान्वयन को परिभाषित करते हैं। कंपाइलर अपने अवकाश के समय foo a = {0} को शुरू करने के लिए स्वतंत्र है (और a, 0, sizeof (a))। पैडिंग बाइट्स को "स्किप" करना और केवल foo.c और foo.i सेट करना आवश्यक नहीं है। (संभावित) सुरक्षा बग tho के लिए +1
SecurityMatt

3
@ लेशेंको बिंदु 19 का कहना है कि "सभी उपविजेता जो स्पष्ट रूप से आरंभिक नहीं हैं", इसलिए मैं दुबला होने के लिए 21 अंक (जो आपने उद्धृत किया है) के लिए झुकाव होगा। यह वास्तव में विचित्र होगा, यदि अंतिम प्रारंभिक के क्षण तक कल्पना को पैडिंग की अनुमति नहीं दी जाती है, जिसके बाद गद्दी को शून्य करना पड़ता है, विशेष रूप से यह देखते हुए कि आरंभिक नामित उपयोग किए जाने पर प्रारंभिक आदेश से बाहर दिखाई दे सकते हैं।
एमएम

20

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

SHELLEXECUTEINFO sexi = {};
char mytext[100] = {};

11

ShellExecuteEx()दुर्घटनाग्रस्त होने के जवाब में : आपकी SHELLEXECUTEINFO"सेक्सी" संरचना में कई सदस्य हैं और आप केवल उनमें से कुछ को शुरू कर रहे हैं।

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

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

SHELLEXECUTEINFO sexi = {0};

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


7

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

char mytext[100] = {0};

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

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

7

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

अदिश प्रकार (अंकगणित और सूचक प्रकार) के लिए, ब्रेसिज़ अनावश्यक हैं, लेकिन उन्हें स्पष्ट रूप से अनुमति है। आईएसओ सी मानक के एन 1570 ड्राफ्ट का हवाला देते हुए , खंड 6.7.9:

एक स्केलर के लिए इनिशलाइज़र एक एकल अभिव्यक्ति होगी, वैकल्पिक रूप से ब्रेसिज़ में संलग्न होगी।

यह ऑब्जेक्ट को शून्य ( 0पूर्णांक के लिए, 0.0फ़्लोटिंग-पॉइंट के लिए, पॉइंटर्स के लिए एक शून्य सूचक) को आरंभीकृत करता है ।

गैर-स्केलर प्रकारों (संरचनाओं, सरणियों, यूनियनों) के लिए, {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यदि यह पूर्णांक है , या अशक्त सूचक है।

नियम C ++ के लिए समान हैं।

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

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


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

3

जब से मैंने c / c ++ लेकिन IIRC में काम किया है, तब से थोड़ी देर हो गई है, एक ही शॉर्टकट का उपयोग सरणियों के लिए भी किया जा सकता है।


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 देखने को कहा जाता है .bss पर विकिपीडिया

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

} my_zero_struct = { 0 };

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

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

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


वैश्विक और स्थिर चर को हमेशा डिफ़ॉल्ट 0 या डिफ़ॉल्ट ctor द्वारा प्रारंभ किया जाता है। लेकिन अगर आप स्थानीय रूप से f का उदाहरण घोषित करते हैं तो आपको अलग परिणाम मिल सकते हैं।
लोगमैन

0

यह खाली / शून्य / शून्य मानों के लिए आपकी संपूर्ण संरचना को आरंभ करने के लिए सिंथेटिक चीनी है।

दीर्घ संस्करण

SHELLEXECUTEINFO sexi;
sexi.cbSize = 0;
sexi.fMask = 0;
sexi.hwnd = NULL;
sexi.lpVerb = NULL;
sexi.lpFile = NULL;
sexi.lpParameters = NULL;
sexi.lpDirectory = NULL;
sexi.nShow = nShow;
sexi.hInstApp = 0;
sexi.lpIDList = NULL;
sexi.lpClass = NULL;
sexi.hkeyClass = 0;
sexi.dwHotKey = 0;
sexi.hMonitor = 0;
sexi.hProcess = 0;

लघु संस्करण

SHELLEXECUTEINFO sexi = {0};

इतना आसान नहीं था?

यह अच्छा भी है क्योंकि:

  • आपको हर सदस्य का शिकार करने और उसे शुरू करने की जरूरत नहीं है
  • आपको यह चिंता करने की ज़रूरत नहीं है कि बाद में जोड़े जाने पर आप नए सदस्यों को प्रारंभ नहीं कर सकते हैं
  • आपको कॉल करने की आवश्यकता नहीं हैZeroMemory

-5

{0} एक अनाम सरणी है जिसका तत्व 0 है।

इसका उपयोग 0 के साथ सरणी के एक या सभी तत्वों को आरंभ करने के लिए किया जाता है

उदा। इंट अरेस्ट [8] = {0};

इस मामले में गिरफ्तारी के सभी तत्वों को 0 के रूप में शुरू किया जाएगा।


4
{0}एक अनाम सरणी नहीं है। यह अभिव्यक्ति भी नहीं है। यह इनिशियल है।
कीथ थॉम्पसन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.