Mikroprocesorowa ośla łączka, część 21
Ostatnia część, podsumowująca, dotycząca instrukcji języka C. Przyjrzymy się dokładniej instrukcjom podstawienia oraz wywołania funkcji. Wydają się proste, ale czasami mogą kryć się w nich niespodzianki.
Działanie programów będzie uruchamiane pod kontrolą symulatora wbudowanego w środowisko Atmel Studio, gdyż zwalnia to nas z budowania odpowiedniego środowiska sprzętowego, a możliwości symulatora są wystarczające, żeby poznać szczegóły ich działania.
Instrukcja podstawienia
To podstawowa instrukcja pozwalająca na realizacje obliczeń. Jej składnia polega na intuicyjnej interpretacji: <zmienna> = <wyrażenie>. Występujący tu znak „=” jest operatorem przypisania, czyli wartość wyrażenia wynikająca z obliczenia <wyrażenie> jest przesłana do miejsca docelowego, identyfikowanego przez nazwę zmiennej. Naturalną rzeczą jest to, by typ wyrażenia (wynikający ze zmiennych i stałych występujących w wyrażeniu) był zgodny z typem miejsca docelowego. Bardzo często nie zachodzi absolutnie doskonała kompatybilność typów obu stron elementów występujących w instrukcji podstawienia i w takich sytuacjach kompilator dokona dopasowania. Czasami może to prowadzić do nieoczekiwanych efektów, o których pisałem w artykule Mikroprocesorowa ośla łączka, część 19, ZE grudzień 2025. Były to dosyć oczywiste działania, choć czasami wynik zaskakiwał, szczególnie przy mieszaniu typów ze znakiem i bez znaku. Obecnie proponuję do rozpatrzenia bardziej „dziwny” przypadek programu, pokazany na listingu 1:
uint16_t Variable1 ;
uint8_t Variable2 [ 5 ] ;
int main ( void )
{
Variable1 = Variable2 ;
while (1)
{
}
}
Następuje tu podstawienie do zmiennej typu 16-bitowej liczby bez znaku, tablicy pięcioelementowej. O dziwo, kompilator wygenerował kod dla takiego programu (nie dostrzegł tu błędów składniowych) a jedynie zgłosił uwagę w kategorii ostrzeżenia (ang. warning), jak widać na rysunku 1.
Sens tego komunikatu należy rozumieć jako próbę przypisania liczby całkowitej ze wskaźnika bez rzutowania. Wszystko brzmi trochę enigmatycznie. Otóż nie następuje tu przepisanie zawartości tablicy do zmiennej 16-bitowej. Tablica jako zmienna bez elementu indeksującego (podania w nawiasach [ ] numeru elementu) jest interpretowana jako wskaźnik (adres) do całej tablicy, w sumie liczba 16-bitowa, pokazuje to rysunek 2 – po uruchomieniu symulacji działania programu.
Z komunikatu ostrzeżenia została wyjaśniona kwestia wskaźnika (czyli adresu) – można podstawić do zmiennej adres dowolnego elementu z programu. Pozostaje jeszcze jego część bez rzutowania. W sytuacjach, gdy zachodzi konflikt reprezentacji, można wymusić odmienne traktowanie wartości. Należy przed wyrażeniem dodać ujęty w nawiasy identyfikator typu, na jaki ma „to być przetłumaczone”. Poprawny zapis (taki, gdzie kompilator nie zgłosił żadnych uwag) przedstawia rysunek 3.
Takim zapisem programista informuje kompilator, że jest świadomy konfliktu typów, ale tak ma być. Próba uruchomienia w symulatorze tego programu daje identyczny wynik.
Taka „sztuczka” daje się wykonać jedynie w przypadku tablic, gdyż taka zmienna jest reprezentowana jako jej adres w pamięci, czyli jako liczba całkowita bez znaku.
(…)
——– ciach! ——–
To jest tylko fragment artykułu, którego pełna wersja ukazała się w lutowym numerze czasopisma Zrozumieć Elektronikę (ZE 2/2026). Pełną wersję czasopisma znajdziesz pod tym linkiem. Natomiast niepełna, okrojona wersja, pozwalająca zapoznać się z zawartością numeru ZE 2/2026 znajduje się tutaj.
Andrzej Pawluczuk
apawluczuk@vp.pl
Uwaga! Wskazówki, jak nabyć pełne wersje dowolnych numerów ZE znajdują się na stronie:
https://piotr-gorecki.pl/n11.


