2013-04-11 17 views
13

Ten program ma dać ostatnie 100 cyfr dowolnej wielkości silni. Jednak jest coś dziwnego w działaniu z counter2 ++ w main(). counter2 jest zwiększane +1 za każdym razem, gdy pętla działa w funkcji main() (99 razy). Jednak to, co jest wyświetlane:Przyrost działa bardzo dziwnie

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 kończy się 1512 zamiast 100, ale jeśli usunąć albo mult (I) lub nosić() z main(), a następnie wyświetla 100. Dlaczego counter2 skończyć ma 1512, a nie 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

jakie jest twoje pytanie? – Raptor

+0

Niestety, dlaczego licznik 2 = 1512? Dlaczego dziwnie się zwiększa? – xyz

+0

Nie ma innego wyjścia, ma to coś wspólnego z pamięcią, jak mówią inni. – xyz

Odpowiedz

14

Piszesz poza końcem tablicy numbers w carry():

 numbers[i+1] += counter; 

Tutaj i może być 99, w którym to przypadku numbers[i+1] jest poza granicami.

Pod względem technicznym jest to undefined behaviour. W praktyce dzieje się tak, że nadpisujesz zmienną count2, która znajduje się w pamięci zaraz po tablicy.

Jedną z nieprzyjemnych rzeczy na temat błędów w pamięci jest to, że przez długi czas mogą one pozostawać bezobjawowe, a następnie wypływać w najgorszych możliwych okolicznościach. valgrind to doskonałe narzędzie do wykrywania problemów tego typu.

+0

Dlaczego ma to wpływ na counter2? – xyz

+0

Również w 'mult' wywołanym z' main', kiedy 'i' jest 100. –

+4

@Seb' counter2' jest całkiem możliwe sąsiadowanie z tablicą w pamięci, więc zapis poza tablicą może napisać 'counter2'. –

2

W tej linii

numbers[i+1] += counter; 

piszesz poza granice tablicy numbers[100];
gdy i == 99 zmieniając wartość int counter2 = 0; który (w Twoim przypadku, ale nie koniecznie) siedzi tuż obok numerów w pamięci.