2013-04-11 29 views
13

Chương trình này được cho là cung cấp cho 100 chữ số cuối cùng của giai thừa quy mô bất kỳ. Tuy nhiên, có một cái gì đó kỳ lạ xảy ra với counter2 ++ trong main(). counter2 được tăng lên +1 cho mỗi lần vòng lặp chạy trong hàm main() (là 99 lần). Tuy nhiên đây là những gì được hiển thị:Sự gia tăng làm việc rất lạ

2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
42 
43 
44 
45 
46 
47 
48 
49 
50 
51 
52 
53 
54 
55 
56 
57 
58 
59 
60 
61 
62 
63 
64 
65 
66 
67 
68 
69 
71 
86 
90 
123 
164 
196 
207 
254 
300 
362 
432 
471 
551 
620 
630 
708 
761 
772 
857 
896 
985 
1036 
1100 
1116 
1207 
1209 
1280 
1356 
1417 
1452 
1512 

Counter2 kết thúc lên được 1512 thay vì 100, nhưng nếu tôi loại bỏ một trong hai mult (i) hoặc thực hiện() từ main() sau đó nó sẽ hiển thị 100. Tại sao counter2 kết thúc là 1512 chứ không phải 100?

#include <iostream> 

using namespace std; 

int numbers[100]; 
int counter2 = 0; 

void init(){ 
//sets elements 1-99 of numbers[] to 0, increments counter2 by 1, sets numbers[0] = 1 
    for (int i = 1; i < 100; i++){ 
     numbers[i] = 0; 
    } 
    numbers[0] = 1; 
    counter2++; 
} 

void mult(int x){ 
//multiplies each element by 1 through n to calculate for !n 
//this is used to represent a very large number without using a BigInt library 
//the nth element is a placeholder for the n+1 position of the number 
//e.g 2nd element represents 100-900 of the number, 4th represents 1000-9000, etc 
//carry() is used to take care of overflow, so that it's only 1 digit per element 
    for (int i = 0; i < 100; i++){ 
     numbers[i] *= x; 
    } 
} 

void carry(){ 
//in order to make previous function work, this adds any overflow to the next 
//element. e.g: 8 * 4 = 32, 3 is added to numbers[i+1], sets numbers[i] to 2 
    int counter = 0; 
    for (int i = 0; i < 100; i++){ 
     if (numbers[i] >= 10){ 
      counter = numbers[i]/10; 
      numbers[i+1] += counter; 
      numbers[i] = numbers[i] % (counter * 10); 
     } 
    } 
} 

int main() 
{ 
    init(); 
    for (int i = 2; i < 101; i++){ 
    //calculates the last 100 digits of !100, but counter2 ends up being 1512 
     mult(i); 
     carry(); 
     counter2++; 
     cout << counter2 << endl; 
    } 
} 
+0

câu hỏi của bạn là gì? – Raptor

+0

Xin lỗi, tại sao counter2 = 1512? Tại sao nó lại tăng lên kỳ lạ? – xyz

+0

Không có đầu ra nào khác, nó phải làm với bộ nhớ khi người khác đang nói. – xyz

Trả lời

14

Bạn đang viết quá khứ cuối của mảng numbers trong carry():

 numbers[i+1] += counter; 

Ở đây, i có thể 99, trong trường hợp numbers[i+1] là ngoài giới hạn.

Về mặt kỹ thuật, đây là undefined behaviour. Điều xảy ra trong thực tế là bạn ghi đè lên biến số count2, xảy ra để ngồi trong bộ nhớ ngay sau mảng.

Một điều khó chịu về lỗi bộ nhớ là chúng có thể đi không có triệu chứng trong một thời gian dài và sau đó xuất hiện trong những trường hợp xấu nhất có thể. valgrind là một công cụ tuyệt vời để phát hiện các vấn đề thuộc loại này.

+0

Tại sao điều đó lại ảnh hưởng đến counter2? – xyz

+0

Cũng trong 'mult' được gọi từ' main', khi 'i' là 100. –

+4

@Seb' counter2' có khả năng nằm gần mảng trong bộ nhớ, do đó, việc ghi bên ngoài mảng có thể ghi 'counter2'. –

2

Trong dòng này

numbers[i+1] += counter; 

bạn đang viết ngoài giới hạn của mảng numbers[100];
khi i == 99 do đó thay đổi giá trị của int counter2 = 0; đó (trong trường hợp của bạn, nhưng không nhất thiết) ngồi ngay bên cạnh con số trong bộ nhớ.

Các vấn đề liên quan