2012-02-13 10 views
33

मैं एक struct फू के लिए प्रारंभ पर ऐसा कर सकते:एक बार में कई मानों को एक स्ट्रक्चर में कैसे असाइन करना है?

Foo foo = {bunch, of, things, initialized}; 

लेकिन, मैं ऐसा नहीं कर सकते:

Foo foo; 
foo = {bunch, of, things, initialized}; 

तो, दो सवाल:

  1. क्यों 'कर सकते हैं मैं बाद में करता हूं, क्या पूर्व में केवल प्रारंभिक के लिए एक विशेष निर्माता है?
  2. मैं दूसरे उदाहरण के समान कुछ कैसे कर सकता हूं, यानी पहले से ही शुरू होने के बाद कोड की एक पंक्ति में संरचना के लिए चर का एक गुच्छा घोषित कर सकता हूं? मैं कई चर के साथ बड़े structs के लिए यह करने के लिए होने से बचने की कोशिश कर रहा हूँ:

    Foo foo; 
    
    foo.a = 1; 
    foo.b = 2; 
    foo.c = 3; 
    //... ad infinitum 
    
+4

"* पूर्व में केवल प्रारंभिक के लिए एक विशेष निर्माता है? *" हां, ठीक है - इसे _gateate प्रारंभिक_ कहा जाता है। – ildjarn

+8

सी या सी ++? एक चुनें। –

+2

सी (++) कुछ क्षेत्रों में बहुत ही प्राचीन है। –

उत्तर

14

पहले एक समग्र प्रारंभकर्ता है - आप उन पर पढ़ सकते हैं और इस समाधान में टैग किया initializers:

What is tagged structure initialization syntax?

यह एक विशेष आरंभीकरण वाक्य रचना है, और आप प्रारंभ के बाद कुछ इसी तरह ऐसा नहीं कर सकते आपकी संरचना का आप क्या कर सकते हैं एक सदस्य (या गैर-सदस्य) फ़ंक्शन प्रदान करने के लिए पैरामीटर के रूप में अपनी श्रृंखलाओं को ले जाने के लिए जो आप तब सदस्य फ़ंक्शन के भीतर असाइन करते हैं - जो आपको संरचना को प्रारंभ करने के बाद इसे पूरा करने की अनुमति देगा संक्षिप्त (फ़ंक्शन को पहली बार फ़ंक्शन लिखने के बाद!)

+0

मुझे यह धागा एक ही प्रश्न पूछने के लिए मिला: http://stackoverflow.com/questions/1705147/struct-initialization-of-the-c-c-programming-भाषा। हालांकि, डेविड (जिसे मैं वास्तव में पसंद करता था और ऊपर उठाया गया) के साथ सभी उत्तरों, संकलक विशिष्ट प्रतीत होता था। यह कुछ ऐसा है जो मैं वास्तव में अपने मंच पर लागू कर सकता हूं, इसलिए मैंने इसे उत्तर के रूप में चुना। सबको शुक्रीया। – jim

25

आज़माएं:

Foo foo; 
foo = (Foo){bunch, of, things, initialized}; 

अगर आप एक अच्छा संकलक है काम करेंगे (उदाहरण के लिए जीसीसी) । आपकोके साथ C99 मोड चालू करने की आवश्यकता हो सकती है, मुझे यकीन नहीं है।

+0

बहुत अच्छा, दुर्भाग्य से, मेरे (खराब) कंपाइलर पर काम नहीं करता है: MSVC2008। :( – jim

+0

@jim: वीसी ++ 2008 "खराब" कंपाइलर नहीं है (हालांकि यह निश्चित रूप से सबसे अच्छा नहीं है); यह केवल सी ++ 11 का समर्थन नहीं करता है, जो आप चाहते हैं उसके लिए आवश्यक है। – ildjarn

+1

समर्थन करता है = अच्छा = जीसीसी? यह तर्कसंगत है। –

3

यदि आपको दक्षता के बारे में बहुत अधिक परवाह नहीं है, तो आप असाइनमेंट को दोहरा सकते हैं: यानी समग्र प्रारंभिकरण का उपयोग करके संरचना का एक नया उदाहरण बनाएं, और फिर इस पर कॉपी:

 
struct Foo foo; 

{ 
    struct Foo __tmp__ = {bunch, of, things, initialized}; 
    foo = __tmp__; 
} 

सुनिश्चित करें कि आप भाग में {लिपटे रखने} इतना है जैसे ही अनावश्यक अस्थायी चर त्यागने के लिए के रूप में यह अब आवश्यक है के रूप में।

ध्यान दें कि यह संरचना के रूप में सक्षम नहीं है, उदाहरण के लिए, स्ट्रक्चर पॉइंटर (यदि सी) को स्वीकार करते हुए संरचना में (सेट सी ++) या संरचना से बाहर 'सेट' फ़ंक्शन। लेकिन अगर आपको त्वरित, अधिमानतः अस्थायी, तत्व-दर-तत्व असाइनमेंट लिखने का विकल्प चाहिए, तो यह हो सकता है।

+0

इसके अलावा कंपाइलर्स इसे अनुकूलित करेंगे। –

+0

क्यों रुकें? 'संरचना फू foo_new (int गुच्छा, int int int, int intized) {struct foo tmp = {गुच्छा, चीजें, प्रारंभिक}; वापसी टीएमपी; }; संरचना फू फू; foo = foo_new (1, 2, 3, 4); 'इसे हेडर फ़ाइल में' इनलाइन 'के रूप में चिपकाएं और प्रदर्शन प्रभाव अनुकूलन के साथ न्यूनतम होना चाहिए। एकमात्र नकारात्मक बात यह है कि आप किसी भी चीज को अंत में शून्य से बाहर नहीं छोड़ सकते हैं (हालांकि कुछ लोग इस बात पर विचार नहीं कर सकते कि 'लापता क्षेत्र-प्रारंभकर्ता' चेतावनी के अस्तित्व को देखते हुए नकारात्मक पक्ष)। बेशक, '(Foo) {...} 'शैली उपलब्ध होने पर शायद सबसे सरल है। – JAB

2

मेमोरी फुटप्रिंट - यहां एक दिलचस्प i386 अतिरिक्त है।

ज्यादा परेशानी के बाद, अनुकूलन और memcpy का उपयोग कर जीसीसी और C99 के साथ छोटी से छोटी i386 का उपयोग कर पदचिह्न उत्पन्न करने के लिए लगता है। मैं यहाँ -O3 का उपयोग कर रहा हूँ। stdlib हाथ में मज़ेदार कंपाइलर अनुकूलन के सभी प्रकार के प्रतीत होता है, और यह उदाहरण उस का उपयोग करता है (memcpy वास्तव में यहां संकलित है)।

कर ऐसा करें:

Foo foo; //some global variable 

void setStructVal (void) { 

    const Foo FOO_ASSIGN_VAL = { //this goes into .rodata 
      .bunch  = 1, 
      .of   = 2, 
      .things  = 3, 
      .initialized = 4 
    }; 

    memcpy((void*) &FOO_ASSIGN_VAL, (void*) foo, sizeof(Foo)); 

    return; 
} 

परिणाम:

  • (.rodata) FOO_ASSIGN_VAL .rodata
  • (.text) में संग्रहीत किया जाता * movl FOO_ASSIGN_VAL के अनुक्रम ,% रजिस्ट्रार *
  • (.text) movl% re का अनुक्रम होता है gisters, foo घटित

उदाहरण:

  • कहो फू uint8_t मूल्यों की एक 48 क्षेत्र struct किया गया था। यह स्मृति में गठबंधन है।

  • (आदर्श) एक 32-बिट मशीन पर, यह foo के पता स्थान के लिए बाहर immediates के रूप में जल्दी के रूप में 12 MOVL निर्देश हो सकता है। मेरे लिए यह आकार में 12 * 10 == 120bytes .text है।

  • (ACTUAL) हालांकि, ऑटो द्वारा उत्तर का उपयोग करने से संभवतः .text में 48 MOVB निर्देश उत्पन्न होंगे। मेरे लिए यह 48 * 7 == 336 बाइट्स .text है !!

  • (SMALLEST *) उपरोक्त memcpy संस्करण का उपयोग करें। यदि संरेखण की देखभाल, ले लिया है

    • FOO_ASSIGN_VAL,
    • 12 MOVL .rodata (48 बाइट्स) में रखा गया है% रजिस्टर में
    • 12% रजिस्टरों से बाहर MOVL .text में किया जाता है (24 * 10) == 240 बाइट्स।
    • मेरे लिए यह कुल 288 बाइट है।

तो, मेरे लिए कम से कम मेरी i386 कोड,

- Ideal: 120 bytes 
- Direct: 336 bytes 
- Smallest: 288 bytes 

के साथ * सबसे छोटा यहाँ 'छोटी से छोटी पदचिह्न मैं के बारे में पता' का अर्थ है। यह उपर्युक्त तरीकों से भी तेज निष्पादित करता है (24 निर्देश बनाम 48)। बेशक, IDEAL संस्करण सबसे तेज़ & सबसे छोटा है, लेकिन मैं अभी भी इसे समझ नहीं सकता।

-Justin

* किसी को भी कैसे 'आदर्श' इनमें से कार्यान्वयन पाने के लिए पता है? यह मेरे बाहर नरक परेशान है !!

7

सी ++ 11 में आप अपने दाहिने हाथ अभिव्यक्ति निश्चित आकार का है, तो "टाई" (टपल शीर्षक में घोषित)

struct foo { 
    int a, b, c; 
} f; 

std::tie(f.a, f.b, f.c) = std::make_tuple(1, 2, 3); 

के साथ कई काम कर सकते हैं और आप केवल से कुछ प्राप्त करने की आवश्यकता तत्वों, आप टाई

std::tie(std::ignore, f.b, std::ignore) = some_tuple; // only f.b modified 

साथ उपेक्षा प्लेसहोल्डर उपयोग कर सकते हैं आप वाक्य रचना std :: टाई (पिता, अमेरिकन प्लान, एफसी) मिल जाए भी कोड को अव्यवस्थित आप संदर्भ की है कि टपल लौटने एक सदस्य समारोह हो सकता था

struct foo { 
    int a, b, c; 
    auto members() -> decltype(std::tie(a, b, c)) { 
     return std::tie(a, b, c); 
    } 
} f; 

f.members() = std::make_tuple(1, 2, 3); 

सभी इस बिल्कुल यह सोचते हैं कि असाइनमेंट ऑपरेटर ओवरलोडिंग एक विकल्प है क्योंकि आपके struct मूल्यों के इस तरह के दृश्य है, जो मामले में आप कह सकते हैं

f = foo(1, 2, 3); 
0

आप दक्षता के बारे में परवाह है, तो आप कर सकते हैं द्वारा constructible नहीं है नहीं है अपनी संरचना के समान लंबाई के एक संघ को परिभाषित करें, एक प्रकार के साथ जिसे आप एक साथ असाइन कर सकते हैं।

तत्वों द्वारा मूल्यों को असाइन करने के लिए, संपूर्ण डेटा असाइन करने के लिए, अपने यूनियन की संरचना का उपयोग करें, अपने अन्य प्रकार के यूनियन का उपयोग करें।

typedef union 
{ 
    struct 
    { 
     char a; 
     char b; 
    } Foo; 
    unsigned int whole; 
} MyUnion; 

MyUnion _Union; 
_Union.Foo.a = 0x23; // assign by element 
_Union.Foo.b = 0x45; // assign by element 
_Union.whole = 0x6789; // assign at once 

अपने मेमोरी संगठन के बारे में सावधान रहें ("ए" एमएसबी या "पूरे" का एलएसबी है?)।

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