2016-11-04 5 views
7

मैं अपने खाली समयसी में, मैं एक अलग चर में किसी सरणी के अंत में लिखे गए मान को क्यों देख सकता हूं?

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

max_arr_count_indexarr[5] मान के आधार पर असाइन किया गया है, जो सरणी +1 के अंत में है।

क्या कोई ऐसा है जो मुझे यह समझा सकता है? मुझे पता है कि यह नहीं होना चाहिए। मैंने मूल्य को पिछले मामले में सरणी (यहां, एआर [5] = 30 समस्या मामले में असाइन किया है) और यह सुरक्षित नहीं है, और यह मानक परिभाषित मानक द्वारा परिभाषित किया गया है।

मैं असली क्षेत्र में वही काम नहीं कर रहा हूं, लेकिन, मैं यहां हुड के नीचे और अधिक प्राप्त करना चाहता हूं।

एलएलवीएम और जीसीसी ने मुझे एक ही परिणाम दिया है।

कोड और परिणाम के नीचे है:

[नो प्रॉब्लम मामले: मैं सूचकांक के अंत अतीत मूल्य निर्दिष्ट नहीं है]:

[before]max_arr_count_index : 5 
[before]The original array elements are : 
arr[0] = 11 
arr[1] = 33 
arr[2] = 55 
arr[3] = 77 
arr[4] = 88 
[after]max_arr_count_index : 5 
[after]The array elements after : 
arr[0] = 1 
arr[1] = 2 
arr[2] = 3 
arr[3] = 4 
arr[4] = 5 
Program ended with exit code: 0 

#include <stdio.h> 

int arr[] = {11,33,55,77,88}; 
int max_arr_count_index = (sizeof(arr)/sizeof(arr[0])); 

// print all 
void print_all_arr(int* arr) 
{ 
    // just print all arr datas regarding index. 
    for(int i = 0; i < max_arr_count_index; i++) { 
     printf("arr[%d] = %d \n", i, arr[i]); 
    } 
} 

int main(int argc, const char * argv[]) { 
    // insert code here... 
    printf("[before]max_arr_count_index : %d\n", max_arr_count_index); 
    printf("[before]The original array elements are :\n"); 
    print_all_arr(arr); 
    arr[0] = 1; 
    arr[1] = 2; 
    arr[2] = 3; 
    arr[3] = 4; 
    arr[4] = 5; 
    // arr[5] = 1000; 
    printf("[after]max_arr_count_index : %d\n", max_arr_count_index); 
    printf("[after]The array elements after :\n"); 

    print_all_arr(arr); 

    return 0; 
} 

कोई समस्या नहीं है परिणाम के नीचे है

[समस्या का मामला: मैंने सूचकांक के पिछले अंत मूल्य को सौंपा]

#include <stdio.h> 

int arr[] = {11,33,55,77,88}; 
int max_arr_count_index = (sizeof(arr)/sizeof(arr[0])); 

// print all 
void print_all_arr(int* arr) 
{ 
    // just print all arr datas regarding index. 
    for(int i = 0; i < max_arr_count_index; i++) { 
     printf("arr[%d] = %d \n", i, arr[i]); 
    } 
} 

int main(int argc, const char * argv[]) { 
    // insert code here... 
    printf("[before]max_arr_count_index : %d\n", max_arr_count_index); 
    printf("[before]The original array elements are :\n"); 
    print_all_arr(arr); 
    arr[0] = 1; 
    arr[1] = 2; 
    arr[2] = 3; 
    arr[3] = 4; 
    arr[4] = 5; 

    /* Point is this one. 
     If I assign arr[5] 30, then, max_arr_count_index is changed also as    
     30. if I assign arr[5] 10000 max_arr_count_index is assigned 10000. 
    */ 

    arr[5] = 30; 

    /* Point is this one. 
     If I assign arr[5] 30, then, max_arr_count_index is changed also as    
     30. if I assign arr[5] 10000 max_arr_count_index is assigned 10000. 
    */ 

    printf("[after]max_arr_count_index : %d\n", max_arr_count_index); 
    printf("[after]The array elements after arr[5] is assigned 30 :\n"); 

    print_all_arr(arr); 

    return 0; 
} 

परिणाम नीचे है:

[before]max_arr_count_index : 5 
[before]The original array elements are : 
arr[0] = 11 
arr[1] = 33 
arr[2] = 55 
arr[3] = 77 
arr[4] = 88 
[after]max_arr_count_index : 30 
[after]The array elements after arr[5] is assigned 30 : 
arr[0] = 1 
arr[1] = 2 
arr[2] = 3 
arr[3] = 4 
arr[4] = 5 
arr[5] = 30 
arr[6] = 0 
arr[7] = 0 
arr[8] = 0 
arr[9] = 0 
arr[10] = 0 
arr[11] = 0 
arr[12] = 0 
arr[13] = 0 
arr[14] = 0 
arr[15] = 0 
arr[16] = 0 
arr[17] = 0 
arr[18] = 0 
arr[19] = 0 
arr[20] = 0 
arr[21] = 0 
arr[22] = 0 
arr[23] = 0 
arr[24] = 0 
arr[25] = 0 
arr[26] = 0 
arr[27] = 0 
arr[28] = 0 
arr[29] = 0 
Program ended with exit code: 0 
+7

एक बार जब आप अपरिभाषित व्यवहार की भूमि में घूमते हैं तो कुछ भी हो सकता है –

उत्तर

7

तो जाहिर है, जहां तक ​​सी मानक का संबंध है, यह अनिर्धारित व्यवहार है, और संकलक make fly demons out of your nose और यह ठीक-ठीक होगा।

लेकिन आप "हूड के तहत" पूछने के लिए गहराई से जाना चाहते हैं, इसलिए हमें अनिवार्य रूप से असेंबलर आउटपुट की तलाश करनी होगी। एक अंश (gcc -g test test.c और objdump -S --disassemble test के साथ उत्पादन) है:

int main(int argc, const char * argv[]) { 
743: 55      push %rbp 
744: 48 89 e5    mov %rsp,%rbp 
747: 48 83 ec 10    sub $0x10,%rsp 
74b: 89 7d fc    mov %edi,-0x4(%rbp) 
74e: 48 89 75 f0    mov %rsi,-0x10(%rbp) 
    // insert code here... 
    printf("[before]max_arr_count_index : %d\n", max_arr_count_index); 
752: 8b 05 fc 08 20 00  mov 0x2008fc(%rip),%eax  # 201054 <max_arr_count_index> 
758: 89 c6     mov %eax,%esi 
75a: 48 8d 3d 37 01 00 00 lea 0x137(%rip),%rdi  # 898 <_IO_stdin_used+0x18> 
761: b8 00 00 00 00   mov $0x0,%eax 
766: e8 35 fe ff ff   callq 5a0 <[email protected]> 
    printf("[before]The original array elements are :\n"); 
76b: 48 8d 3d 4e 01 00 00 lea 0x14e(%rip),%rdi  # 8c0 <_IO_stdin_used+0x40> 
772: e8 19 fe ff ff   callq 590 <[email protected]> 
    print_all_arr(arr); 
777: 48 8d 3d c2 08 20 00 lea 0x2008c2(%rip),%rdi  # 201040 <arr> 
77e: e8 6d ff ff ff   callq 6f0 <print_all_arr> 
    arr[0] = 1; 
783: c7 05 b3 08 20 00 01 movl $0x1,0x2008b3(%rip)  # 201040 <arr> 
78a: 00 00 00 
    arr[1] = 2; 
78d: c7 05 ad 08 20 00 02 movl $0x2,0x2008ad(%rip)  # 201044 <arr+0x4> 
794: 00 00 00 
    arr[2] = 3; 
797: c7 05 a7 08 20 00 03 movl $0x3,0x2008a7(%rip)  # 201048 <arr+0x8> 
79e: 00 00 00 
    arr[3] = 4; 
7a1: c7 05 a1 08 20 00 04 movl $0x4,0x2008a1(%rip)  # 20104c <arr+0xc> 
7a8: 00 00 00 
    arr[4] = 5; 
7ab: c7 05 9b 08 20 00 05 movl $0x5,0x20089b(%rip)  # 201050 <arr+0x10> 
7b2: 00 00 00 
    /* Point is this one. 
     If I assign arr[5] 30, then, max_arr_count_index is changed also as    
     30. if I assign arr[5] 10000 max_arr_count_index is assigned 10000. 
    */ 

    arr[5] = 30; 
7b5: c7 05 95 08 20 00 1e movl $0x1e,0x200895(%rip)  # 201054 <max_arr_count_index> 
7bc: 00 00 00 
    /* Point is this one. 
     If I assign arr[5] 30, then, max_arr_count_index is changed also as    
     30. if I assign arr[5] 10000 max_arr_count_index is assigned 10000. 
    */ 

    printf("[after]max_arr_count_index : %d\n", max_arr_count_index); 
7bf: 8b 05 8f 08 20 00  mov 0x20088f(%rip),%eax  # 201054 <max_arr_count_index> 
7c5: 89 c6     mov %eax,%esi 
7c7: 48 8d 3d 22 01 00 00 lea 0x122(%rip),%rdi  # 8f0 <_IO_stdin_used+0x70> 
7ce: b8 00 00 00 00   mov $0x0,%eax 
7d3: e8 c8 fd ff ff   callq 5a0 <[email protected]> 
    printf("[after]The array elements after insertion :\n"); 
7d8: 48 8d 3d 39 01 00 00 lea 0x139(%rip),%rdi  # 918 <_IO_stdin_used+0x98> 
7df: e8 ac fd ff ff   callq 590 <[email protected]> 

    print_all_arr(arr); 
7e4: 48 8d 3d 55 08 20 00 lea 0x200855(%rip),%rdi  # 201040 <arr> 
7eb: e8 00 ff ff ff   callq 6f0 <print_all_arr> 

    return 0; 
7f0: b8 00 00 00 00   mov $0x0,%eax 
} 

आप देख सकते हैं, यहां तक ​​कि उस स्तर पर, disassembler पहले से ही जानता है कि आप प्रभावी रूप से max_arr_count_index की स्थापना कर रहे हैं। पर क्यों?

यह क्योंकि स्मृति लेआउट जीसीसी द्वारा उत्पादित बस उस तरह से है (और हम उसे वहां एम्बेड डिबग जानकारी बनाने के लिए gcc साथ -g इस्तेमाल किया ताकि disassembler पता कर सकते हैं जो स्मृति स्थान है जो क्षेत्र है)। आपके पास पांच इंच की वैश्विक सरणी है, और एक वैश्विक int चर, एक दूसरे के बाद सही घोषित किया गया है। ग्लोबल इंट वैरिएबल मेमोरी में सरणी के ठीक पीछे है। सरणी के अंत के पीछे पूर्णांक तक पहुंचने से max_arr_count_index मिलता है।

याद रखें कि एक सरणी i किसी सरणी arr के उदाहरण के लिए int एस है (कम से कम सभी आर्किटेक्चर I पता है) बस स्मृति स्थान arr+sizeof(int)*i तक पहुंच रहा है, जहां arr पहले तत्व का पता है।

जैसा कि कहा गया है, यह अपरिभाषित व्यवहार है। जीसीसी सरणी से पहले ग्लोबल इंट वैरिएबल को भी ऑर्डर कर सकता है, जिससे arr[5] तक पहुंचने का प्रयास करते समय संभवतः प्रोग्राम समाप्त हो रहा है, यदि उस स्थान पर कोई वैध मेमोरी पेज नहीं है।

+0

यूप। असेंबलर आउटपुट की जांच करना एक अच्छा तरीका है। Upvoted। – Bathsheba

+0

आपके शांत असेंबली दृष्टिकोण के लिए धन्यवाद। यह पूरी तरह से समझाया गया है। – boraseoksoon

7

सीमा से बाहर तक पहुँचना सरणी अपरिभाषित व्यवहार आह्वान। इस मामले में कुछ भी अच्छा उम्मीद नहीं की जा सकती है। arr का आकार 5 है। आप arr[0] से arr[4] तक पहुंच सकते हैं।

व्यवहार

/* Point is this one. 
    If I assign arr[5] 30, then, max_arr_count_index is changed also as    
    30. if I assign arr[5] 10000 max_arr_count_index is assigned 10000. 
*/ 

के लिए ले रहा है यूबी एक पल के लिए अलग, स्पष्टीकरण किया जा सकता है चर max_arr_count_index सिर्फ सरणी arr के बाद घोषित किया जाता है। कंपाइलर max_arr_count_index के लिए स्मृति को आवंटित कर सकता है, केवल अंतिम तत्व सरणी arr से पहले। उदाहरण के लिए, यदि arr[4]0x100 पर है तो max_arr_count_index के लिए स्मृति 0x104 पर आवंटित की गई है। तो सरणी arr से पहले पता 0x104 है। चूंकि &arr[5]max_arr_count_index के समान पता है, arr[5] पर एक मान निर्दिष्ट करने के लिए max_arr_count_index के पते पर यह मान लिखें। कृपया ध्यान दें कि यह वास्तव में नहीं हो रहा है। यह इस व्यवहार के लिए एक अंतर्ज्ञान है। एक बार यूबी होने के बाद सभी दांव बंद हो जाते हैं।

3

अपरिभाषित व्यवहार पर सवाल उठाने के लिए एक निश्चित तरीके से ऑक्सीमोरोनिक और डाउनवॉटिंग के लिए एक नुस्खा है।

arr[i]*(arr + i) के रूप में मूल्यांकन किया जाता है: लेकिन इस आधार पर मैं पहले से ही आज के लिए प्रतिष्ठा टोपी मारा और तो काफी है कि के बारे में अधिक आराम कर रहा हूँ गया है, यहाँ मेरी राजनीतिक संदेश है। यह स्पष्ट है कि arr और max_arr_count_index के बीच शायद कोई पैडिंग नहीं है, इसलिए arr + 5 शायद &max_arr_count_index के बराबर है। लेकिन पॉइंटर अंकगणित केवल में मान्य है। आप सरणी के अंत में एक पॉइंटर सेट कर सकते हैं, लेकिन पर व्यवहार पर व्यवहार अपरिभाषित है।

बेशक, दूसरे दिन, कंपाइलर आपकी बिल्ली खा सकता था।

+3

यह सवाल डाउनवॉटिंग के लिए नुस्खा कैसे है? मुझे अकसर आश्चर्य होता है कि ऐसा कुछ गलत तरीके से क्यों करता है। ये प्रश्न गहरी समझ के लिए प्रदान कर सकते हैं कि चीजें हुड के नीचे कैसे काम करती हैं। – glglgl

3

आप arr के बाद max_arr_count_index घोषित, तो max_arr_count_indexarr को अगले ही पता सापेक्ष में शायद है, इसलिए arr+5 को एक काम max_arr_count_index पता करने के लिए एक काम है।

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

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