środa, 11 września 2013

Unikanie błędów programując w C - #1 liczby całkowite ze znakiem i bez

Postanowiłem napisać cykl krótkich artykułów (a właściwie porad) dla osób, które zaczynają programować systemy wbudowane w języku C. Skłonił mnie do tego sposób w jaki piszą studenci, którzy odbywają praktyki (lub dorabiają sobie) u nas w firmie. Ich kod jest mało czytelny, zajmuje dużo miejsca po skompilowaniu i zawiera dużo błędów, które nie ujawniają się od razu ale dopiero np. po włączeniu optymalizacji, dopisaniu kolejnego fragmentu kodu lub w losowych momentach.

Na pierwszy ogień idą liczby całkowite ze znakiem i bez.

Liczby całkowite ze znakiem nie powinny być używane z liczbami całkowitymi bez znaku w porównaniach lub innych wyrażeniach.

//Nie rób tego...
uint8_t a = 6u;
int8_t b = -9;

if (a + b < 4) {
    //program powinien iść tą prawidłową ścieżką
    //bo -9 + 6 = -3 < 4
} else {
    //ale wykona się ten fragment ponieważ 
    // -9 + 6 stanie się dla kompilatora
    // (256 - 9) + 6 = 253.
    // 247 (bez znaku) == -9 ze znakiem
}

Powyższy program skompilowany i uruchomiony na 8-bitowym AVR wykona się tak jak opisałem w komentarzach. Co ciekawe jeśli skompilujesz ten kod u siebie na komputerze to wykona się poprawnie (zgodnie z przewidywaniami). Dzieje się to dlatego, że pracujesz na 32 lub 64 bitowym procesorze i rejestry mają taką długość. Zmień jednak typ zmiennych na np. uint32_t i int32_t a zadziała jak na AVR :)