Kompilator nie wykryje żadnego błędu, a kod zostanie skompilowany i wykonany. Dlatego, aby zobaczyć, co się stanie, musimy odkryć magię zakulisową. Aby podsumować, przejdź do końca.
Druga linia w twoim kodzie to miejsce magii i tam musimy się skupić.
pinMode(pin, OUTPUT);
Część pinModeistotna dla tej dyskusji to:
void pinMode(uint8_t pin, uint8_t mode)
{
uint8_t bit = digitalPinToBitMask(pin); //The first instance where pin is used
uint8_t port = digitalPinToPort(pin);
if (port == NOT_A_PIN) return;
//Do something
}
(Pełną implementację można znaleźć w wiring_digital.c )
digitalPinToBitMaskWydaje się , że tutaj używa się pindo obliczenia bitu pośredniego. Dalsza eksploracja digitalPinToBitMaskto zdefiniowane makro, Arduino.hktórego definicją jest ten jednoliniowy:
#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )
Ta dziwnie wyglądająca jedna wkładka wykonuje bardzo proste zadanie. Indeksuje Pty element w tablicy digital_pin_to_bit_mask_PGMi zwraca go. Ta tablica digital_pin_to_bit_mask_PGMjest zdefiniowana w pins_arduino.hlub mapie pinów dla używanej konkretnej płytki.
const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = {
_BV(0), /* 0, port D */
_BV(1),
_BV(2),
_BV(3),
_BV(4),
_BV(5),
_BV(6),
_BV(7),
...
};
Ta tablica ma w sumie 20 elementów, więc nie mamy szczęścia. 999 zindeksuje miejsce w pamięci flash poza tą tablicą, co prowadzi do nieprzewidzianych zachowań. Czy to będzie?
Nadal mamy inną linię obrony przed anarchią środowiska uruchomieniowego. Jest to następny wiersz funkcji pinMode:
uint8_t port = digitalPinToPort(pin);
digitalPinToPortprowadzi nas podobną ścieżką. Jest on definiowany jako makro wraz z digitalPinToBitMask. Jego definicja to:
#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) )
Teraz indeksujemy Pty element, digital_pin_to_port_PGMktórego tablica jest zdefiniowana w mapie pinów:
const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
PD, /* 0 */
PD,
....
PC,
PC,
};
Ta tablica zawiera 20 elementów, więc 999 znów jest poza zasięgiem. Ponownie to polecenie odczytuje i zwraca wartość z pamięci flash, której wartości nie możemy być pewni. To znów doprowadzi do nieprzewidzianych zachowań.
Jest jeszcze jedna ostatnia linia obrony. To jest ifsprawdzenie pinModewartości zwracanej digitalPinToPort:
if (port == NOT_A_PIN) return;
NOT_A_PINjest zdefiniowany jako 0 cali Arduino.h. Tak więc, jeśli zwracany bajt z digitalPinToPortma wartość zero, wówczas pinModepo cichu zawiedzie i zwróci.
W każdym razie pinModenie może nas ocalić od anarchii. 999 ma doprowadzić do zguby.
TL; DR, kod zostanie wykonany, a jego wynik będzie nieprzewidywalny. Najprawdopodobniej żaden pin nie zostanie ustawiony na OUTPUTi digitalWritezawiedzie. Jeśli zdarzy ci się wyjątkowo niefortunnie, wtedy losowy pin może zostać ustawiony na OUTPUT, i digitalWritemoże to ustawić HIGH.