Thread View: pl.comp.lang.c
15 messages
15 total messages
Started by heby
Sun, 10 Mar 2024 11:07
stała mapa enum -> wartość
Author: heby
Date: Sun, 10 Mar 2024 11:07
Date: Sun, 10 Mar 2024 11:07
49 lines
1385 bytes
1385 bytes
Cześć. Jest: enum class Foo : unsigned char { [...] }; Gdzieś indziej mam w programi potrzebę następujacą: Bar getBarFromFoo( Foo _foo ) { [...] } Mapowanie jest stałe przez cały czas trwania programu. Enumeratorów jest dużo (prawie 200). Nie wszystkie 256 wartości są wypełnione, dziury są nieregularne. Nie istnieje jakiś sensowny pattern mapowania, jest praktycznie randomowy. Chciałbym, najprościej, dostać jakąs taką translację: Bar bar[256]; i czytać to przez bar[(int)_foo]. Tablica bar powinna być we flash (system embedded) więc jakiekolwiek mapy "normalne" odpadają, chodzi o wygenerowanie jej na stałe i sięganie jedną instrukcją asm. Mam dwie opcje: 1) napisać mały programik w C++ który zaczya definicję enumeratora Foo, zaczyta tablicę translacji Foo->Bar, wypełni struktury a następnie zrzuci te 256 bajtów do pliku 2) To samo w pythone, ale wtedy nie będzie łatow odczytać oryginalny enumerator (jego wartości). Potem te 256 bajtowe pliki można zapakować do .o i zlinkować do programu jako "dane we flash". Jest jakies kretywne rozwiązanie inicjacji tej tablicy bez wygibasów przez zewnatrzne programy? Czyli coś jak: Bar bar[256] = magic::assign_map< Foo:One, Bar(30) >[...]. Aby wykonało się to wszystko na compile time i podczas linkowania była już tylko tablica 256 bajtów, zainicjowana.
Re: stała mapa enum -> wartość
Author: Jacek Marcin Jaw
Date: Mon, 11 Mar 2024 01:03
Date: Mon, 11 Mar 2024 01:03
10 lines
459 bytes
459 bytes
W dniu 10.03.2024 o 11:07, heby pisze: > > Jest jakies kretywne rozwiązanie inicjacji tej tablicy bez wygibasów > przez zewnatrzne programy? Konwertery i generatory to standard i właściwe rozw. (przede wszystkim ekonomiczne i skuteczne, bo robią co trzeba). Normalnie koduje je się jako pierwsze przy rozp. nowego proj. Piszesz chaotycznie. Jest wrażenie, że ma to się kompilować na systemie wbudowanym. Mimo, że wydaje się to nonsensowne.
Re: stała mapa enum -> wartość
Author: heby
Date: Mon, 11 Mar 2024 16:34
Date: Mon, 11 Mar 2024 16:34
17 lines
568 bytes
568 bytes
On 11/03/2024 01:03, Jacek Marcin Jaworski wrote: > Konwertery i generatory to standard i właściwe rozw. (przede wszystkim > ekonomiczne i skuteczne, bo robią co trzeba). Normalnie koduje je się > jako pierwsze przy rozp. nowego proj. Tutaj muszę wygenerować jednorazowo 256 bajtów. Pisanie do tego "generatora" jest mało sensowne. > Jest wrażenie, że ma to się kompilować na systemie > wbudowanym. To pewnie wrażenie wynikajace z tego zdania: "Tablica bar powinna być we flash (system embedded)" > Mimo, że wydaje się to nonsensowne. Mi nie.
Re: stała mapa enum -> wartość
Author: JDX
Date: Mon, 11 Mar 2024 17:18
Date: Mon, 11 Mar 2024 17:18
30 lines
1386 bytes
1386 bytes
On 11.03.2024 16:34, heby wrote: > On 11/03/2024 01:03, Jacek Marcin Jaworski wrote: >> Konwertery i generatory to standard i właściwe rozw. (przede wszystkim >> ekonomiczne i skuteczne, bo robią co trzeba). Normalnie koduje je się >> jako pierwsze przy rozp. nowego proj. > > Tutaj muszę wygenerować jednorazowo 256 bajtów. Pisanie do tego > "generatora" jest mało sensowne. Nie bardzo rozumiem w czym jest problem. Tzn. rozumiem, że funkcję Bar = f(Foo) masz już gdzieś jakoś zdefiniowaną/opisaną (np. na kartce papieru czy wewnątrz funkcji getBarFromFoo()). W czym więc problem, aby jednorazowo przepisać („wygenerować”) tę funkcję do pliku .cpp zawierającego np. coś w stylu: const Bar foo2bar[256] = { /* opcjonalnie „static const” */ Bar(7), Bar(2), (Bar)0, /* 0 -> wartość „niezdefiniowana */ Bar(1), ... }; Zakładam, że bar jest typem typu POD. Taka tablica powinna wylądować w sekcji .rodata (mówimy oczywiście o jedynie słusznym gcc), która na platformie klasy „mały embedded” powinna z kolei wylądować we Flashu. Ewentualnie, aby nie było żadnych wątpliwości, należy pobawić się z __attribute__ ((section ("nazwa sekcji"))) (https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html) i domyślnie używanym skryptem linkera (być może wystarczy go przeczytać, niekoniecznie modyfikować).
Re: stała mapa enum -> wartość
Author: heby
Date: Mon, 11 Mar 2024 17:36
Date: Mon, 11 Mar 2024 17:36
37 lines
1764 bytes
1764 bytes
On 11/03/2024 17:18, JDX wrote: >> Tutaj muszę wygenerować jednorazowo 256 bajtów. Pisanie do tego >> "generatora" jest mało sensowne. > Nie bardzo rozumiem w czym jest problem. Tzn. rozumiem, że funkcję > Bar = f(Foo) masz już gdzieś jakoś zdefiniowaną/opisaną (np. na kartce > papieru czy wewnątrz funkcji getBarFromFoo()). W czym więc problem, aby > jednorazowo przepisać („wygenerować”) tę funkcję do pliku .cpp > zawierającego np. coś w stylu: > const Bar foo2bar[256] = { /* opcjonalnie „static const” */ > Bar(7), > Bar(2), > (Bar)0, /* 0 -> wartość „niezdefiniowana */ > Bar(1), > ... > }; Widzisz, zakładasz, że potrafisz "zgadnąć" kolejnośc enumeratorów Foo. Ona nie jest stabilna. Jak ktoś doda/usunie enumerator Foo, to ta tablica tego automatycznie nie dostosuje. To generuje ciężkie do odnalezienia błędy. Ja wiem, że Foo:X1 mapuje się na Bar(3,4). Ale Foo::X2 na Bar(15,2). Który element tablicy to Foo::X1 to wie tylko kompilator. Nigdzie nawet nie podaję wartości liczbowych dla tego enumeratora, wyliczają się "same". Aby taka deklaracja jak powyżej działała, musiałbym pozbyć się Foo::X1 i pozostałych oraz liczyć na szczęscie, że prawidłowo uda mi się utrzymać niejawnie numery tablicy vs odpowienie Bar wpisując na pałę po kolei Bar. Tymczasem ja wiem tylko, że Foo::X1->Bar(3,4) i chciałbym, aby to "Bar(3,4)" wylądowało automatycznie na właściwej pozycji tablicy bez względu na manipulacje przy enumeratorze Foo i jego wartości liczbowe w danym momencie. > Taka tablica powinna wylądować w sekcji .rodata Z tym nie ma problemu, tak zrobię, jak się nie trafi rozsądne wyjście na etapie kompilacji.
Re: =?ISO-8859-2?Q?sta³a?= mapa enum -> =?ISO-8859-2?Q?warto¶æ?
Author: arnold@hootervil
Date: Tue, 12 Mar 2024 02:37
Date: Tue, 12 Mar 2024 02:37
15 lines
575 bytes
575 bytes
heby <heby@poczta.onet.pl> wrote: > Ona nie jest stabilna. Jak kto¶ doda/usunie enumerator Foo, to ta > tablica tego automatycznie nie dostosuje. To generuje ciê¿kie do > odnalezienia b³êdy. Czasem nie do unikniêcia (nie mówiê, ¿e konkretnie tutaj tak jest). Wtedy po prostu zostawiam komentarz w stylu: uwaga, zmieniaj±c to-i-to zmieñ te¿ to-i-to. -- Panie doktorze, ka¿dej nocy ¶ni± mi siê nagie dziewczêta, jak wbiegaj± i wybiegaj± z pokoju. - I chce pan, ¿eby ten sen siê nie pojawia³? - Nie, tylko chcia³em spytaæ, co zrobiæ, ¿eby one tak nie trzaska³y drzwiami.
Re: =?ISO-8859-2?Q?sta³a?= mapa enum -> =?ISO-8859-2?Q?warto¶æ?
Author: arnold@hootervil
Date: Tue, 12 Mar 2024 02:43
Date: Tue, 12 Mar 2024 02:43
24 lines
1104 bytes
1104 bytes
heby <heby@poczta.onet.pl> wrote: > Ja wiem, ¿e Foo:X1 mapuje siê na Bar(3,4). Ale Foo::X2 na Bar(15,2). > Który element tablicy to Foo::X1 to wie tylko kompilator. Nigdzie nawet > nie podajê warto¶ci liczbowych dla tego enumeratora, wyliczaj± siê "same". Chyba pozostaje napisanie skryptu uruchamianego przed kompilacj±. Niech wygeneruje jeden plik ¼ród³owy z funkcj± mapuj±c±. Dodaj ten plik do wykluczeñ w systemie kontroli wersji (albo wrzucaj do innego katalogu, który jest ju¿ wykluczony), ¿eby siê przypadkiem kiedy¶ nie wcommitowa³. > Tymczasem ja wiem tylko, ¿e Foo::X1->Bar(3,4) i chcia³bym, aby to > "Bar(3,4)" wyl±dowa³o automatycznie na w³a¶ciwej pozycji tablicy bez > wzglêdu na manipulacje przy enumeratorze Foo i jego warto¶ci liczbowe w > danym momencie. Czy ta wiedza (jak foo mapuje siê na bar) jest potrzebna w programie, czy tylko w funkcji, która ma byæ wygenerowana wspomnianym generatorem? -- Sanitariusze wioz± karetk± pacjenta. - Dok±d jedziemy? - pyta pacjent. - Do kostnicy - odpowiada sanitariusz. - Ale ja jeszcze nie umar³em. - A my jeszcze nie dojechali¶my.
Re: stała mapa enum -> wartość
Author: heby
Date: Tue, 12 Mar 2024 07:23
Date: Tue, 12 Mar 2024 07:23
8 lines
498 bytes
498 bytes
On 12/03/2024 03:43, Arnold Ziffel wrote: >> Tymczasem ja wiem tylko, że Foo::X1->Bar(3,4) i chciałbym, aby to >> "Bar(3,4)" wylądowało automatycznie na właściwej pozycji tablicy bez >> względu na manipulacje przy enumeratorze Foo i jego wartości liczbowe w >> danym momencie. > Czy ta wiedza (jak foo mapuje się na bar) jest potrzebna w programie, czy > tylko w funkcji, która ma być wygenerowana wspomnianym generatorem? Z grubsza istnieje tylko jeden punkt, Bar getBarFromFoo( Foo );
Re: stała mapa enum -> wartość
Author: JDX
Date: Tue, 12 Mar 2024 07:56
Date: Tue, 12 Mar 2024 07:56
12 lines
777 bytes
777 bytes
On 11.03.2024 17:36, heby wrote: [...] > Widzisz, zakładasz, że potrafisz "zgadnąć" kolejnośc enumeratorów Foo. > Ona nie jest stabilna. Jak ktoś doda/usunie enumerator Foo, to ta > tablica tego automatycznie nie dostosuje. To generuje ciężkie do > odnalezienia błędy. Tak, o tym nie pomyślałem. W każdym razie temat mnie zainteresował, trochę poszukałem i znalazłem np. taką odpowiedź: https://stackoverflow.com/questions/33374241/compile-time-lookup-table-for-enum. Zwłaszcza jedno zdanie zwróciło moją uwagę (o czym w zasadzie wiedziałem, ale jakoś nie przyszło mi to do głowy): „In C++14, your switch function could be constexpr, thanks to relaxed constexpr restrictions” – ja bym właśnie z constexpr spróbował się pobawić.
Re: stała mapa enum -> wartość
Author: heby
Date: Tue, 12 Mar 2024 08:23
Date: Tue, 12 Mar 2024 08:23
9 lines
784 bytes
784 bytes
On 12/03/2024 07:56, JDX wrote: > https://stackoverflow.com/questions/33374241/compile-time-lookup-table-for-enum. Zwłaszcza jedno zdanie zwróciło moją uwagę (o czym w zasadzie wiedziałem, ale jakoś nie przyszło mi to do głowy): „In C++14, your switch function could be constexpr, thanks to relaxed constexpr restrictions” – ja bym właśnie z constexpr spróbował się pobawić. Nie spradzałem tego konkretnego rozwiązania jeszcze, zerknę. Jednak z konwersją switch()->tablica mam złe doświadczenia - być może implementacja gcc na tą arch jakoś specjalnie nie lubi się z tablicami i zarówno w AVR jak i ARM dostawałem setkę ifów w asm. Lub też zalezy od zwracanego typu - u mnie jest to struct z polami bitowymi, choć mieszczący się w bajcie.
Re: stała mapa enum -> wartość
Author: JDX
Date: Wed, 13 Mar 2024 01:19
Date: Wed, 13 Mar 2024 01:19
75 lines
2518 bytes
2518 bytes
On 12.03.2024 08:23, heby wrote: > On 12/03/2024 07:56, JDX wrote: >> https://stackoverflow.com/questions/33374241/compile-time-lookup-table-for-enum. Zwłaszcza jedno zdanie zwróciło moją uwagę (o czym w zasadzie wiedziałem, ale jakoś nie przyszło mi to do głowy): „In C++14, your switch function could be constexpr, thanks to relaxed constexpr restrictions” – ja bym właśnie z constexpr spróbował się pobawić. > > Nie spradzałem tego konkretnego rozwiązania jeszcze, zerknę. A ja z ciekawości właśnie sprawdziłem i wygląda na to, że działa. A w bonusie jest zerowe zużycie pamięci (nie trzeba tablicy). ----------------------------------------------------------------- // Kompilacja: g++ -std=c++20 -O3 -Wall -S testenum.cpp #include <cstdint> #include <type_traits> enum class Foo : uint8_t { D, U, P, A }; struct Bar { uint8_t a; uint32_t b; constexpr Bar(uint8_t _a, uint32_t _b) : a(_a), b(_b) {} }; template<Foo> struct Foo2Bar; // "Tablica" mapujaca Foo -> Bar template<> struct Foo2Bar<Foo::D> : std::integral_constant<Bar, Bar(7,3)> { }; template<> struct Foo2Bar<Foo::U> : std::integral_constant<Bar, Bar(0,0)> { }; template<> struct Foo2Bar<Foo::P> : std::integral_constant<Bar, Bar(2,3)> { }; template<> struct Foo2Bar<Foo::A> : std::integral_constant<Bar, Bar(1,5)> { }; int footest() { // oczekiwana wartosc zwracana: 21 static_assert( Foo2Bar<Foo::D>::value.a + Foo2Bar<Foo::D>::value.b + Foo2Bar<Foo::U>::value.a + Foo2Bar<Foo::U>::value.b + Foo2Bar<Foo::P>::value.a + Foo2Bar<Foo::P>::value.b + Foo2Bar<Foo::A>::value.a + Foo2Bar<Foo::A>::value.b == 21, ""); return Foo2Bar<Foo::D>::value.a + Foo2Bar<Foo::D>::value.b + Foo2Bar<Foo::U>::value.a + Foo2Bar<Foo::U>::value.b + Foo2Bar<Foo::P>::value.a + Foo2Bar<Foo::P>::value.b + Foo2Bar<Foo::A>::value.a + Foo2Bar<Foo::A>::value.b; } const Bar& bartest() { return Foo2Bar<Foo::D>::value; } ----------------------------------------------------------------- Dla typów prostych nie potrzeba -std=c++20. W każdym razie np. dla ARM-a footest() wygląda tak: .global _Z7footestv .syntax unified .arm .type _Z7footestv, %function _Z7footestv: .fnstart .LFB14: @ Function supports interworking. @ args = 0, pretend = 0, frame = 0 @ frame_needed = 0, uses_anonymous_args = 0 @ link register save eliminated. mov r0, #21 bx lr .cantunwind .fnend .size _Z7footestv, .-_Z7footestv Przy optymalizacji -O0 ładnie widać jak pracowicie są dodawane poszczególne stałe.
Re: stała mapa enum -> wartość
Author: heby
Date: Wed, 13 Mar 2024 09:16
Date: Wed, 13 Mar 2024 09:16
7 lines
238 bytes
238 bytes
On 13/03/2024 01:19, JDX wrote: > const Bar& bartest() > { > return Foo2Bar<Foo::D>::value; > } Teraz zamień powyższe Foo:D na zmienną. Gdyby to była stała, zamiast kombinować, użyłbym boost::mpl::map. Ale jest zmienna.
Re: stała mapa enum -> wartość
Author: heby
Date: Wed, 13 Mar 2024 09:21
Date: Wed, 13 Mar 2024 09:21
32 lines
767 bytes
767 bytes
On 10/03/2024 11:07, heby wrote: > Jest jakies kretywne rozwiązanie inicjacji tej tablicy bez wygibasów > przez zewnatrzne programy? Znalazłem głupie i źle działajace "rozwiązanie", ale może warto wiedziec, że jest i takie: enum class Foo { X , Y [...] } class Bar { [...] } const Bar tablica[256] = { [Foo:X] = Bar(0,1) , [Foo:Y] = Bar(3,4) [...] } Zalety: 1) Niemożliwe zrobienie błednego mapowania Wady: 1) To zachowuje się jak inicjacja pól klasy - jest runtime, a nie we flash. 2) Nie można zmieniać kolejności enumeratorów 3) Nie można robić dziur (za wyjatkiem końca wyliczenia) 4) enumerator Foo nie może mieć dziur (X=1, Y=3 nie przejdzie) Czyli nie to, co chcę, ale przyznam, że składni nie znałem. Bodaj z C99.
Re: stała mapa enum -> wartość
Author: Jacek Marcin Jaw
Date: Thu, 21 Mar 2024 16:20
Date: Thu, 21 Mar 2024 16:20
30 lines
943 bytes
943 bytes
W dniu 10.03.2024 o 11:07, heby pisze: > Cześć. > > Jest: > > enum class Foo : unsigned char { > [...] > }; > > Gdzieś indziej mam w programi potrzebę następujacą: > > Bar getBarFromFoo( Foo _foo ) > { > [...] > } Tak sobie pomyślałem, że można to rozw. podobnie jak z plikami zasobów qrc z Qt: 1. Należy zakodować prog. konsoli generujący plik binarny z tablicą 256 bajtów generowanych f. getBarFromFoo; 2. Należy zakodować drugi prog. konwertujący ten plik do kodu źródłowego w j. C. Po prostu będzie tworzył tablice: unsigned char [] tablica = { 0xYY, 0xYY, 0xYY, 0xYY, 0xYY, 0xYY, ...}; 3. Należy tylko włączyć ten plik do proj. 4. Skompilować całość. Mi się wydaje to proste i eleganckie. Jest też niezależne od kompilatora. Przy okazji: Ja mogę w tym pomóc za jakąś sensowną kwotę. Jestem w stanie też napisać testy automatyczne do tych programików, bo to dobry zwyczaj.
Re: stała mapa enum -> wartość
Author: heby
Date: Thu, 21 Mar 2024 16:44
Date: Thu, 21 Mar 2024 16:44
26 lines
1016 bytes
1016 bytes
On 21/03/2024 16:20, Jacek Marcin Jaworski wrote: > 1. Należy zakodować prog. konsoli generujący plik binarny z tablicą 256 > bajtów generowanych f. getBarFromFoo; To opcja typu generator. Z jej "zakodowaniem" w konsoli problem jest taki, że nie jest on synchroniczny ze zmianami w pliku enumeratorów. Należało by zrobić parser tych plików, nawet jakiś prymitywny, a to już duża komplikacja. Albo napisać ten generator w cpp, ale to komplikuje znowu budowanie, bo muszę mieć wtedy dwa kompilatory, natywny i cross (to oprogramowanie embedded). Jest jeszcze opcja typu skryptowy c, jak "Ch", ale to już grube przegięcie IMHO, to są już języki ezotryczne i coś czuje że i tak nie poradzą sobie z nowszą składnią enuma. > Przy okazji: Ja mogę w tym pomóc za jakąś sensowną kwotę. Spokojnie, to jest trywialne zagadnienie, ja tylko akademicko pytam jak to zrobić elegancko. Obecnie mam generator w cpp i jak nie będzie jakiegoś super rozwiązania, to tak zostanie.
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads