Chciałem *bezpiecznie*. Może nie być prosto. Ja widziałem nieprostą implementację w C na makrach.
Aby były *bezpieczne*.
Tego właśnie detalu nie pojmujesz. C++ robi rzeczy bezpieczniej niż C. Te same i często bezkosztowo.
Chciałem *bezpiecznie*. Może nie być prosto. Ja widziałem nieprostą implementację w C na makrach.
Aby były *bezpieczne*.
Tego właśnie detalu nie pojmujesz. C++ robi rzeczy bezpieczniej niż C. Te same i często bezkosztowo.
Co jest niebezpieczne w moim przykładzie? Niebezpieczne to jest właśnie przekombinowanie jak to zrobić "lepiej".
PA1 ^=1; ?
Wybrałeś sobie prymitywny przykład, więc niebezpieczeńśtwo jest mniejsze.
Mój był inny.
Może tak:
setupUart( F_UART_SINGLE_BIT_MULTIPLY | F_UART_CONTROL | UART_SPEED_9600 );
Ten kod zawiera błąd.
Jest - mniej więcej - podobny do faktycznego kodu w systemie, gdzie szukałem kiedyś niedziałajacego UARTu, tylko tych flag było nascie o bardzo różnych nazwach.
Wyjaśnię na czym polega problem:
#define UART_SPEED_9600 4 #define F_UART_SPEED_9600 (1<<UART_SPEED_9600)
Już rozumiesz? Funkcja zaakceptowała #define z i bez F_. A powinna tylko z F_, bo tak jest zaimplemnetowana, ze przyjmuje maski a nie numery bitów. Ta wiedza, maska czy numer bitu, nie istnieje nigdzie, bo to prymitywny C. Ba, nawet nie wiadomo do której to fukcji są flagi. To tylko nazwane numerki.
Nikt tego nie kontroluje, funkcja przyjmuje cokolwiek i jedyna nadzieja w białku, które pisze kod, że się nie pomyli. Naiwna.
Takich funkcji w kodzie są setki.
Być może inaczej definicujesz słowo "niebezpiecznie".
Funkcjonalnośc została przerobiona tak, że nie dało się już podać flagi bez F_ mimo, że obie były liczbami. Wymagało to napisania kilkudziesięciu lini w C++ i zmiany z #define na class enum.
C++ pozwolił mi zatkać źródło błędu którego nie da się w sposób sensowny zatkać w samym C z uwagi na prymitywizm wyrażania intencji.
Bezkosztowo. Podczas implementacji nie ucierpiał ani jeden mnemonik asemblera a przy okazji znalazły się jeszcze dwa takie same przypadki dla innych elementów systemu, gdzie pomylono flagi.
Po kilku latach pytałem jeszcze kolegi, mieli to w użyciu cały czas i używali dla nowych funkcji.
Deklaracja dla klienta kodu zmieniał się z: setupUart( int _flags ) na setupUart( flags<UartFlags> _flags )
Gdzie UartFlags było wyliczniem co wolno za pomocą prostego template. Całosc redukuje się do 1 liczby na kompilacji, jak dla C.
I tyle. Reszta nikogo nie interesowała.
Dzieki C++ jestem w stanie napisać teraz kod, który w wypadku pomylenia flagi, zatrzyma kompilację, zamiast wesoło zrzucić problem na frajera z debuggerem.
Rozumiesz już po co jest ten C++?
Miało być miganie diodą.
O a teraz się wykręcasz czymś przekombinowanym na 2 strony maszynopisu.
Czyli nawet nie zrozumiałeś o co chodziło z tym "miganiem diodą".
Wyjasnie: "miganie diodą" oznacza tak prosty kod na uC, że jakakolwiek technika napisania go jest dobra. To miejsce, gdzie C++ jest zbędny. Całkiem sporo kodu embedded ma taki poziom komplikacji.
Co ciekawe, nawet Arduino wymusza pisanie w C++, tylko mało kto zauważył. Uważam to za przezabawne.
Natomiast przykład, który zaprezentowałem przed chwilą i wcześniej, dotyczy flag i ich grupowania w sposób pewny w argumentach funkcji, aby uniemożliwić błąd.
Takich przykładów jest więcej, na przykład zwalnianie zasobów sprzetowych z użyciem RIIA albo statyczny polimorfizm w celu testowania kodu poza mikrokontrolerem bez utraty prędkości i kompromisów.
Do migania diodą C++ jest zbędny, choć i tak go używasz w Arduino.
W dniu 18.05.2023 o 13:29, Grzegorz Niemirowski pisze:
Aaa to o to chodzi, czyli funkcja sizeof jest po prostu do dupy i tyle. To że są w jednej pamięci to wiem doskonale i wiem czym się kończy nadpisanie zmiennych. Już trochę programów 'popełniłem'.
Nie, ty go dobrze użyłes tylko funkcja jest źle napisana, ma błędy. Akurat ja sie na niej nie naciąłem bo używałem swojej :) a była ona częścią funkcji specyficznie formatującej ciąg.
Nie ma, liczy się wiedza i doświadczenie, jak już będziesz miał sklerozę taką jak ja to sie nauczysz żyć z przypominaczami.
W dniu 18.05.2023 o 13:08, Dawid Rutkowski pisze:
Guzik się dowiem, funkcja jest skopana i tyle.
Wiem pisałem w nim.
Cały czas teraz właśnie w nim piszę, C na małe procki.
że OP pisze tu o jakichś wyjątkach, może to w wersji mips pod jakimś unixem.
Masz na myśli monitor od mery? czy pulpit operatorski bo to z niego wklepywało się te kilka komend w asemblerze. Owszem był jakiś kompilator asemblera obsługujący monitory ale to do czegoś wiekszego się nadawało a ja przy naprawach takich potrzeb nie miałem.
czwartek, 18 maja 2023 o 21:12:57 UTC+2 Janusz napisał(a):
sizeof() to nie funkcja tylko operator. Użycie nawiasów nie oznacza wywołania funkcji, for oraz if też je mają.
I wiesz, że sprawdza zakresy tablic w runtime, a C nie?
Na duże jest tak samo. Różnicę wnosi OS + ochrona pamięci.
W dniu 18.05.2023 o 21:29, Dawid Rutkowski pisze:
A tego to nie wiedziałem.
A nie sa czasami elementami składni?
Dlatego pisałem że pisałem w nim, ale to też można było wyłączyć.
No nie różnic jest więcej, ale to tu bez znaczenia.
I tu wchodzi C++, cały na biało.
Możesz miec lub nie, bounds checking. Kwestia wyboru [] albo "at". To nie jest std::vector. To najzwyklejsza tablica C z opcjonalnymi bajerami.
On 18.05.2023 14:13, Dawid Rutkowski wrote: [...]
A co rozumiesz przez wyjątek/exception? Bo to ma różne znaczenia:
On 18.05.2023 21:12, Janusz wrote: [...]
Nigdy nie było żadnego kompilatora assemblera na jakąkolwiek platformę… :-)
On 18.05.2023 16:16, Dawid Rutkowski wrote: [...]
On 18.05.2023 16:40, heby wrote: [...]
Masz pomysł jak zceplusplusować typowe definicje SFR-ów znane z C, np:
/* Power Control */ #define PCON (*((volatile unsigned char *) 0xE01FC0C0)) #define PCONP (*((volatile unsigned long *) 0xE01FC0C4))
Tak, aby to było w „duchu C++”. Może referencje?
volatile unsigned char &PCON = (*((volatile unsigned char *) 0xE01FC0C0)); volatile unsigned long &PCONP = (*((volatile unsigned long *) 0xE01FC0C4));
A co konkretnie chcesz osiągnąć?
O enkapsulację, aby byle kto/co tak łatwo nie mógł mazać po tych rejestrach. Czyli aby te rejestry były prywatnymi polami klasy, coś w stylu:
class PowerMgmt { private: volatile unsigned char &refPCON = (*((volatile unsigned char *)
0xE01FC0C0)); volatile unsigned long &refPCONP = (*((volatile unsigned long *) 0xE01FC0C4)); };On 18.05.2023 15:37, heby wrote: [...]
No nie, zupełnie nie za darmo. Trzeba poświęcić sporo czasu na dokształcanie, aby efektywnie używać nowego języka. Aby np. dowiedzieć się, że w ogóle istnieje coś takiego jak std::size(). Bo sama zamiana, bez podstaw „teoretycznych”, kompilatora C na kompilator C++ nie ma większego sensu. Chodzi o to, aby używać C++, a nie „C z klasami”.
private: void setPCON( ... value );
Jeszcz lepiej: public: void allowSleep(); void wakeUp(); bool isSleeping() const;
private: [...magic...]
On 18.05.2023 18:29, heby wrote: [...]
No Panie, ale jak za pomocą std::size() otrzymać rozmiar tablicy w bajtach? :-)
Have something to add? Share your thoughts — no account required.
Ask the community — no account required