2012-09-30 9 views
9

मैं एक struct के रूप में परिभाषितincrementing struct सदस्यों

struct my_struct 
{ 
    int num; 
}; 

....

यहाँ मैं my_struct के लिए सूचक है और मैं पर एक वेतन वृद्धि करना चाहते हैं इस प्रकार है कहो num

void foo(struct my_struct* my_ptr) 
{ 
    // increment num 
    // method #1 
    my_ptr->num++; 

    // method #2 
    ++(my_ptr->num); 

    // method #3 
    my_ptr->++num; 

} 

num बढ़ाने के इन 3 तरीके क्या एक ही काम करते हैं? जबकि हम इसमें हैं, क्या यह सच है कि पूर्व-वृद्धि वृद्धि के बाद से अधिक कुशल है?

धन्यवाद!

उत्तर

8

पहले दो का एक ही प्रभाव होगा (जब उनकी तरह एक लाइन पर), लेकिन तीसरी विधि वैध सी कोड नहीं है (आप वहां ++ नहीं डाल सकते हैं)।

दक्षता के लिए, कोई अंतर नहीं है। जब आप सी ++ में बात करते हैं तो अंतर यह है कि आप एक गैर-सूचक डेटा प्रकार, जैसे कि इटरेटर को बढ़ाते हैं। कुछ मामलों में, पूर्व-वृद्धि वहां तेजी से हो सकती है।

आप GCC Explorer का उपयोग कर जेनरेट कोड देख सकते हैं।

void foo(struct my_struct* my_ptr) 
{ 
    my_ptr->num++; 
} 

void bar(struct my_struct* my_ptr) 
{ 
    ++(my_ptr->num); 
} 

आउटपुट:

foo(my_struct*):      # @foo(my_struct*) 
    incl (%rdi) 
    ret 

bar(my_struct*):      # @bar(my_struct*) 
    incl (%rdi) 
    ret 

जैसा कि आप देख सकते हैं, वहाँ जो भी कोई अंतर नहीं है।

पहले दोनों के बीच ही संभव अंतर नहीं है जब आप उन्हें भाव में उपयोग करें:

my_ptr->num = 0; 
int x = my_ptr->num++; // x = 0 

my_ptr->num = 0; 
int y = ++my_ptr->num; // y = 1 
2

अपने ही इरादा संख्या का मान बढ़ाने के लिए है, तो 1 और 2 विधि एक ही intented परिणाम के लिए निकलेगा कैली विधि।

हालांकि, यदि आप निम्नलिखित के लिए अपने कोड बदलने के लिए, आप जीसीसी (विधानसभा स्तर कोड) द्वारा बनाया गया कोड के बीच का अंतर देख सकते:

struct my_struct 
{ 
    int num; 
}; 

void foo(struct my_struct* my_ptr) 
{ 
     printf("\nPost Increment: %d", my_ptr->num++); 
} 

int main() 
{ 
     struct my_struct a; 
     a.num = 10; 

     foo(&a); 
} 

अब का उपयोग कर इसे संकलन: जीसीसी -masm = इंटेल - एस structTest.c -o structTest.s यह असेंबली कोड उत्पन्न करने के लिए जीसीसी से पूछता है:

एक टेक्स्ट एडिटर में structTest.s खोलें।

foo: 
.LFB0: 
     push rbp 
     mov  rbp, rsp 
     sub  rsp, 16 
     **mov  QWORD PTR [rbp-8], rdi** 
     mov  rax, QWORD PTR [rbp-8] 
     mov  eax, DWORD PTR [rax] 
     mov  edx, eax 
     **lea  ecx, [rax+1]** 
     mov  rax, QWORD PTR [rbp-8] 
     mov  DWORD PTR [rax], ecx 
     mov  eax, OFFSET FLAT:.LC0 
     mov  esi, edx 
     mov  rdi, rax 
     mov  eax, 0 
     call printf 
     leave 
     ret 
     .cfi_endproc 

main: 
.LFB1: 
     push rbp 
     mov  rbp, rsp 
     sub  rsp, 16 
     **mov  DWORD PTR [rbp-16], 10 
     lea  rax, [rbp-16] 
     mov  rdi, rax 
     call foo** 
     leave 
     ret 
     .cfi_endproc 

और जब आप पहले से वेतन वृद्धि के लिए आपरेशन बदलने के लिए, follwoing कोड उत्पन्न होता है:

foo: 
.LFB0: 
     .cfi_startproc 
     push rbp 
     mov  rbp, rsp 
     sub  rsp, 16 
     **mov  QWORD PTR [rbp-8], rdi** 
     mov  rax, QWORD PTR [rbp-8] 
     mov  eax, DWORD PTR [rax] 
     **lea  edx, [rax+1]** 
     mov  rax, QWORD PTR [rbp-8] 
     **mov  DWORD PTR [rax], edx** 
     mov  rax, QWORD PTR [rbp-8] 
     **mov  edx, DWORD PTR [rax]** 
     mov  eax, OFFSET FLAT:.LC0 
     mov  esi, edx 
     mov  rdi, rax 
     mov  eax, 0 
     call printf 
     leave 
     ret 
     .cfi_endproc 

तो, आप दूसरे मामले में है कि देखना होगा, संकलक संख्या मूल्य और पास में जुड़ जाता printf() के लिए इस num मान पर।

प्रदर्शन के संदर्भ में, मैं उम्मीद करता हूं कि वृद्धि के बाद और अधिक कुशल होने की उम्मीद है क्योंकि स्मृति स्थानों को कम संख्या में छुआ जाता है।

महत्वपूर्ण लाइनों को ऊपर दिए गए कोड में ** के बीच चिह्नित किया गया है।

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