2012-02-23 15 views
7

Czytając jakieś pytanie na stronie natknąłem poniżej pytanie gdzie ac pytanie musi być debugowaniaJak debugowania kodu w języku C

unsigned int a, b, c; 
/* a and b are assume to have some values */ 
c = (a + b)/2; // <- There is a bug in this st 
What is the bug? and how you debug it? 

Niektóre odpowiedzi mówiąc, może to spowodować przepełnienie (C = (a + b)/2) .Ale naprawdę nie rozumiem jak to powoduje przepełnienie?

+0

Czy możesz podać link do strony? – Bazooka

+0

http://geeksforgeeks.org/forum/topic/how-to-debug-the-c-code#post-36549 –

Odpowiedz

5

Jeśli a i/lub b są bardzo duże, a następnie a + b może przekroczyć maksymalnej wielkości liczba całkowita bez znaku (patrz MAX_UINT w pliku limits.h). To spowodowałoby przepełnienie, więc wynik byłby nieprawidłowy. Na przykład jeśli a i b są równe 0x80000000, wynikiem będzie 0 w 32-bitowej arytmetyki, a nie oczekiwany wynik 0x80000000.

Aby rozwiązać go można użyć coś takiego zamiast:

c = a/2 + b/2 + (a % 2 == 1 && b % 2 == 1); 

Jeśli wiesz, że b jest większa niż a następnie można użyć to nieco prostszą wersję:

c = a + (b - a)/2; 

Przeczytaj ten artykuł aby uzyskać informacje o tym, jak ten błąd pojawił się w algorytmach wyszukiwania binarnego w popularnych językach (choć mówi się o signed int zamiast unsigned int):

+0

@larsmans: Tak, artykuł jest głównie (ale nie do końca, jeśli czytasz uważnie) o Java's 'signed int'. Ale powód, dla którego zawarłem link, nie był tak bardzo, ponieważ bezpośrednio odpowiada na pytanie (artykuł tego nie robi), ale bardziej dlatego, że uważam, że zapewnia on użyteczne tło * dlaczego * to pytanie jest interesujące/trafne i * dlaczego * znajomość odpowiedzi może być ważna. –

0

może powodować nadmiaru jeśli a i b są wystarczająco wysokie do uzyskania produktu a + b większa niż maksymalna reprezentowana przez unsigned int.

8

a+b może wypłynąć, jeśli suma a i b jest większa niż UINT_MAX, maksymalną wartość dla unsigned int. Np

unsigned a = 1; 
unsigned b = UINT_MAX; 

printf("%u\n", (a+b)/2); 

drukuje 0.

Jeśli chcesz znaleźć średnią z dwóch unsigned int s bez przelewu, zrobić

c = a/2 + b/2 + (a % 2 & b % 2); 

(lub (a%2 + b%2)/2 lub (a%2 && b%2) lub ((a&1) & (b&1)), etc.)

+1

ta odpowiedź sprawiła, że ​​również zadałem pytanie. – SashaN

0

Jeśli tylko zadeklarować zmienną C bez zainicjowania go, dostaje nieprzewidywalnie wartości. aib mogą być pewną wartością, która jest aktualnie pod adresem, który dostają w pamięci.

Możesz debugowania kodu C w Eclipse CDT
http://www.eclipse.org/cdt/

Z tego IDE można programować w C++ i C anc zawiera debuggera gdb.
http://www.gnu.org/software/gdb/

2

Jako inny powie:

unsigned int a, b, c; 
c = (a + b)/2; 

a + b nie mogą być odwzorowane w unsigned int jakiegoś wartości a i b.

Bardzo podobna sytuacja doprowadziła do słynnego błędu w standardowej implementacji wyszukiwania binarnego Java (funkcja binarySearch).

Zobacz ten słynny Joshua Blosh blogu w roku 2006:

"Extra, Extra - Read All About It: prawie wszystkie binarne wyszukiwań i Mergesorts są łamane" http://googleresearch.blogspot.com/2006/06/extra-extra-read-all-about-it-nearly.html

Fragmenty:

Błąd znajduje się w tym wierszu:

6: int mid = (niski + wysoki)/2;

dalej:

Więc co jest najlepszym sposobem, aby naprawić ten błąd? Oto jeden sposób:

6: int mid = niski + ((wysoki - niski)/2);

Należy zauważyć, że w Joshua postu, high jest >= low a także int obiekty zostały wykorzystane, ale traktuje Java podpisane przepełnienie jako opakowania. W przepełnieniu całkowitym ze znakiem C są niezdefiniowane zachowanie i niepodpisana obwiednia.

+0

+1 dla punktu, w którym dokonałeś około połowy = niski + ((wysoki-niski)/2) –

+0

@Amit: W odpowiedzi umieściłem te same informacje, z wyjątkiem tego, że wysłałem godzinę wcześniej. Połączyłem też ten sam artykuł, co ten post. I uwzględniłem również rozwiązanie najwyższej głosowanej odpowiedzi (a także zanim ją opublikował). Nie zrozum mnie źle, nie jestem zmartwiony, jestem tylko trochę ciekawy ... dlaczego nie dostałem również od ciebie uprowadzenia? Czy moja odpowiedź była trudna do zrozumienia? Jakoś tego nie zauważyłeś? Proszę, powiedz mi, co zrobiłem źle, abym mógł poprawić moje odpowiedzi w przyszłości. –

+0

Hej @ Mark Już głosuję na Ciebie i naprawdę dziękuję za pomoc. –

Powiązane problemy