2013-05-06 15 views
6

Mam tablicę liczb całkowitych bez znaku, które muszą przechowywać wskaźniki dla danych i funkcji, a także niektóre dane. W urządzeniu, z którym pracuję, wielkość wskaźnika jest taka sama jak rozmiar unsigned int. Jak rzucić wskaźnik do funkcji w unsigned int? Wiem, że to sprawia, że ​​kod nie jest przenośny, ale jest on specyficzny dla mikrokontrolerów. Próbowałem to:Wskaźnik funkcji Casting do Integer w C++

stackPtr[4] = reinterpret_cast<unsigned int>(task_ptr); 

ale to daje mi błąd „nieprawidłowy konwersji typu”

Casting go unieważnić, a następnie wskaźnik do int jest niechlujny.

stackPtr[4] = reinterpret_cast<unsigned int>(static_cast<void *> (task_ptr)); 

Czy jest to czysty sposób?

Edit - task_ptr jest funkcja wskaźnik void task_ptr(void)

odpowiedź Miłość Barmar za, zapiera mi przenośność mankament hotelu. Również tablica pustego wskaźnika ma więcej sensu niż niepodpisane wartości Ints. Dziękuję Barmar i isaach1000.

EDYCJA 2: Rozumiem, mój kompilator myśli o dużym modelu pamięci, więc używa 32-bitowych wskaźników, nie 16-bitowych, których oczekiwałem (małe mikroskopy o całkowitej pamięci 17K).

+1

Nie możesz utworzyć tablicy pustych wskaźników? – isaach1000

+4

Co powiesz na połączenie wskaźników funkcji i wskaźników danych? – Barmar

+1

Prosta 'reinterpret_cast' powinna działać tak długo, jak (a) typ całkowity jest wystarczająco duży i (b) jest wskaźnikiem dla normalnej (nieczłonkowej lub statycznej składowej) funkcji. Czy tak jest w tym przypadku? Czym dokładnie jest 'task_ptr'? –

Odpowiedz

4

Odlew w stylu C może pasować do ośmiokątnego kołka do trapezoidalnej dziury, więc powiedziałbym, że biorąc pod uwagę twój bardzo specyficzny sprzęt i wymagania, użyłbym tej obsady, ewentualnie opakowanej w szablon dla większej przejrzystości.

Ewentualnie podwójna obsada do void*, a następnie ma tę zaletę, że sprawia, że ​​kod wyróżnia się jak bolesny kciuk, więc przyszli opiekunowie wiedzą, że coś się dzieje i mogą zwrócić szczególną uwagę.

EDYCJA dla komentarza: Wygląda na to, że Twój kompilator może mieć błąd. Poniższy kod kompiluje na g ++ 4.5:

#include <iostream> 

int f() 
{ 
    return 0; 
} 

int main() 
{ 
    int value = (int)&f; 

    std::cout << value << std::endl; 
} 

Edit2: Można również rozważyć użycie typu intptr_t zamiast int. Jest to typ integralny wystarczająco duży, aby pomieścić wskaźnik.

+0

Kompilator C++ zwraca błąd, gdy używam stylu C: 'Błąd [Pe171]: niepoprawna konwersja typów' – user1135541

+1

+1 dla 'intptr_t' – Oktalist

+1

Niestety,' intptr_t' nie jest określony, aby umożliwić przywrócenie skonwertowanych wskaźników funkcyjnych tak jak w przypadku wskaźników obiektów i nie ma odpowiednika dla wskaźników funkcji :-(Tak więc nie ma oczywistego sposobu, aby upewnić się, że twój kod nie skompiluje się na systemach, w których wskaźniki funkcji nie zmieszczą się w 'intptr_t'. – SamB

-1

Jest to zgodne z ANSI:

int MyFunc(void* p) 
{ 
    return 1; 
} 

int main() 
{ 
    int arr[2]; 
    int (*foo)(int*); 

    arr[0] = (int)(MyFunc); 

    foo = (int (*)(int*))(arr[0]); 

    arr[1] = (*foo)(NULL); 
} 
+0

Próbowałem, ale mój C++ narzeka, 'nieważna konwersja typu. \ Potrzebuję standardowego sposobu C++ robienia tego – user1135541

+0

To też dobrze kompiluje się w C++.Jak dokładny błąd dostałeś? – lsalamon

+3

Kiedy ostatnio sprawdzałem,' void main() ' był niestandardowy –

2

W C++ wskaźnik można przekształcić na wartość integralnego rodzaju na tyle dużej, aby utrzymać. Obsługiwany warunkowo typ std::intptr_t jest zdefiniowany w taki sposób, że można przekonwertować wartość void* na intptr_t i cofnąć, aby uzyskać oryginalną wartość. Jeśli void* ma rozmiar równy lub większy niż wskaźniki funkcji na platformie, możesz wykonać konwersję w następujący sposób.

#include <cstdint> 
#include <cassert> 

void foo() {} 

int main() { 
    void (*a)() = &foo; 

    std::intptr_t b = reinterpret_cast<std::intptr_t>(a); 

    void (*c)() = reinterpret_cast<void(*)()>(b); 
    assert(a==c); 
} 
+0

Jest również obsługiwany warunkowo, niezależnie od tego, czy 'a' można ponownie zinterpretować-rzutować na' b', nawet jeśli istnieje 'intptr_t'. (Jednak jest zagwarantowane, że jeśli takie wsparcie istnieje, to 'a == c'). –

Powiązane problemy