Czy jest jakiś sposób, że mogę wykryć typ zmiennej automatycznie w C, albo przez jakiś mechanizm w samym programie, albo - bardziej prawdopodobny - poprzez wstępną kompilację skrypt, który wykorzystuje przepustki kompilatora do punktu, w którym przeanalizował zmienne i przypisał im ich typy? Szukam ogólnych sugestii na ten temat. Poniżej znajduje się więcej informacji o tym, czego potrzebuję i dlaczego.Uzyskiwanie typu zmiennej w kodzie C
Chciałbym zmienić semantykę klauzuli redukcji OpenMP. W tym momencie wydaje się najłatwiej po prostu zamienić klauzulę w kodzie źródłowym (poprzez skrypt) na wywołanie funkcji, a następnie mogę zdefiniować funkcję implementacji semantyki redukcji, jakiej chcę. Na przykład, mój skrypt będzie przekonwertować ten
#pragma omp parallel for reduction(+:x)
w tym:
my_reduction(PLUS, &x, sizeof(x));
#pragma omp parallel for
gdzie wcześniej, mam (powiedzmy)
enum reduction_op {PLUS, MINUS, TIMES, AND,
OR, BIT_AND, BIT_OR, BIT_XOR, /* ... */};
I my_reduction
ma podpis
void my_reduction(enum reduction_op op, void * var, size_t size);
Wśród innych t hings, my_reduction
musiałby zastosować operację dodawania do zmiennej redukcji, jak pierwotnie zamierzał programista. Ale moja funkcja nie może wiedzieć, jak to zrobić poprawnie. W szczególności, chociaż zna rodzaj operacji (PLUS
), lokalizacja oryginalnej zmiennej (var
), a także rozmiar typu zmiennej, nie zna samego typu zmiennej. W szczególności nie wiadomo, czy var
ma typ całkowy czy zmiennoprzecinkowy. Z POV o niskim poziomie operacja dodawania dla tych dwóch klas typów jest zupełnie inna.
Jeśli tylko niestandardowy operator typeof
, który obsługuje GCC, działałby tak, jak działa sizeof - zwracając rodzaj zmiennej - mógłbym łatwo rozwiązać ten problem. Ale typeof nie jest tak naprawdę sizeof: może być użyty tylko w deklaracjach L-value.
Teraz kompilator oczywiście nie zna typu x przed zakończeniem generowania kodu wykonywalnego. Prowadzi mnie to do zastanawiania się, czy mogę w jakiś sposób wykorzystać parser GCC, aby uzyskać typ x
i przekazać go do mojego skryptu, a następnie ponownie uruchomić GCC, aby skompilować mój zmieniony kod źródłowy. Byłoby wtedy być proste wystarczy zadeklarować
enum var_type { INT8, UINT8, INT16, UINT16, /* ,..., */ FLOAT, DOUBLE};
void my_reduction(enum reduction_op op, void * var, enum var_type vtype);
And my_reduction
może oddać odpowiednio przed dereferencji i stosowania operatora.
Jak widać, próbuję stworzyć rodzaj mechanizmu "dyspozytorskiego" w C. Dlaczego po prostu nie używać przeciążania C++? Ponieważ mój projekt ogranicza mnie do pracy ze starszym kodem źródłowym napisanym w C. Mogę zmienić kod automatycznie za pomocą skryptu, ale nie mogę go przepisać na inny język.
Dzięki!
Co powiesz na przetwarzanie kodu źródłowego za pomocą niektórych narzędzi/skryptów? Na przykład. przeanalizować go za pomocą języka, znaleźć typy, wstawić/dostosować kod specyficzny dla typu, skompilować? –
Dzięki, Alex. To brzmi jak idzie w dobrym kierunku. –
Czytałem gdzieś, że zdefiniowana przez użytkownika redukcja będzie częścią standardu 3.1 lub 4.0. Hm 3.1 mówi: 'reduction ({operator | nazwa_procedury_wirtualnej}: list)' .. once tried nazwa_procedury_wejściowej. chociaż tylko częściowo rozwiązuje wykrywanie typu. – Bort