2010-08-05 28 views
9

Czy to prawda?Jak zadeklarować wskaźnik do funkcji, która zwraca wskaźnik do tablicy wartości int w C/C++?

int (*(*ptr)())[]; 

Wiem, że to banalne, ale szukałem na starym teście o tego rodzaju konstrukcji, a ta konkretna kombinacja nie było na teście i to naprawdę doprowadza mnie do szału; Muszę się tylko upewnić. Czy istnieje wyraźna i solidna i zrozumiała zasada dla takich deklaracji? (tj .: wskaźnik do ... tablicy ... wskaźników do ... funkcji, które .... itp. Itp.) Dzięki!

R

+4

+1 za wiodący tytuł, który sprawił, że mój mózg został ranny! (Plus nazwa: P) – Russell

+0

Prawdopodobnie może to zrobić, ale pamiętaj o spiralnej regule zgodnej z ruchem wskazówek zegara, działa ona w obie strony, po prostu dostosuj kierunek. – jer

+0

Czy funkcja :: function jest czymś, co można zaakceptować? –

Odpowiedz

13

The right-left rule ułatwia.

int (*(*ptr)())[]; można interpretować jako

zacząć od nazwy zmiennej ------------------------------- ptr

Nic do prawej, ale ) więc idź w lewo, aby znaleźć * -------------- jest wskaźnikiem

wyskoczyć z nawiasami i spotkać () --- -------- do funkcji, która nie przyjmuje argumentów (w przypadku C nieokreślonej liczby argumentów)

Przejdź w lewo, znajdź * --------------------------- --------------------- i zwraca wskaźnik

Skacz z nawiasów, idź w prawo i uderz [] --------- - do tablicy

Go znowu w lewo, znaleźć int --------------------------------- ---- ints.

+3

Nie ma w tym nic łatwego. Lubię używać typedefs, żeby trochę go rozbić. –

+0

Pamiętaj jednak, że przykład nie jest prawidłową deklaracją - aby go ustawić, należy określić rozmiar tablicy. – caf

+2

@caf: Sprawia, że ​​typ jest niekompletny, ale nadal możesz użyć wskaźnika do niekompletnego typu w deklaracji. –

0

Oto moje rozwiązanie ...

int** (*func)(); 

funktora powrocie tablicę int * 's. To nie jest tak skomplikowane jak twoje rozwiązanie.

1

Korzystanie cdecl pojawić się następujący

cdecl> declare a as pointer to function returning pointer to array of int; 
Warning: Unsupported in C -- 'Pointer to array of unspecified dimension' 
    (maybe you mean "pointer to object") 
int (*(*a)())[] 

This question z C-faq jest podobny, ale zapewnia 3 podejścia do rozwiązania problemu.

5

W prawie wszystkich sytuacjach, w których chcesz zwrócić wskaźnik do tablicy, najprościej jest zwrócić wskaźnik do pierwszego elementu tablicy. Wskaźnik ten może być użyty w tych samych kontekstach, co nazwa tablicy i nie zapewnia mniejszego lub mniejszego kierunku niż zwracanie wskaźnika typu "wskaźnik do tablicy", w rzeczy samej zachowa on tę samą wartość wskaźnika.

Jeśli to zrobisz, chcesz wskaźnik do funkcji zwracającej wskaźnik do int. Możesz to zbudować (konstrukcja deklaracji jest łatwiejsza niż parsowanie).

Wskaźnik do int:

int *A; 

Funkcja powrocie wskaźnik int:

int *fn(); 

wskaźnik do funkcji powrocie wskaźnik do int:

int *(*pfn)(); 

Jeśli naprawdę chcesz zwrócić wskaźnik do funkcji zwracającej wskaźnik do tablicy int, możesz wykonać ten sam proces.

Array int:

int A[]; 

Wskaźnik do tablicy int:

int (*p)[]; 

Funkcja zwraca wskaźnik ...:

int (*fn())[]; 

Wskaźnik do fn ...:

int (*(*pfn)())[]; 

który jest tym, co masz.

1

Jeśli czujesz oszukiwania:

typedef int(*PtrToArray)[5]; 
PtrToArray function(); 

int i = function; 

Kompilacja że na gcc plonów: invalid conversion from 'int (*(*)())[5]' to 'int'. Pierwszy bit to rodzaj, którego szukasz.

Oczywiście, kiedy już masz swój typ PtrToArray, całe ćwiczenie staje się bardziej banalne, ale czasami jest to przydatne, jeśli masz już nazwę funkcji i musisz ją gdzieś trzymać. I z jakiegokolwiek powodu nie można polegać na oszustwie szablonów, aby ukryć przed tobą krwawe szczegóły.

Jeśli kompilator wspiera go, można też to zrobić:

typedef int(*PtrToArray)[5]; 
PtrToArray function(); 

template<typename T> void print(T) { 
    cout << __PRETTY_FUNCTION__ << endl; 
} 

print(function); 

, które w mojej skrzynce komputerowej, produkuje void function(T) [with T = int (* (*)())[5]]

Będąc w stanie odczytać typów jest dość przydatne, ponieważ zrozumienie błędów kompilatora często zależy od twojej zdolności do określenia, co wszystkie te nawiasy oznaczają. Ale samo ich tworzenie jest mniej przydatne, IMO.

2

Nie musisz. Po prostu podziel go na dwa typy: jeden dla wskaźnika na tablicę int i jeden dla wskaźnika do funkcji. Coś jak:

typedef int (*IntArrayPtr_t)[]; 
typedef IntArrayPtr_t (*GetIntArrayFuncPtr_t)(void); 

ta jest nie tylko bardziej czytelny, ale również sprawia, że ​​łatwiej zadeklarować/zdefiniowanie funkcji, że idziesz do przypisania zmiennej:

IntArrayPtr_t GetColumnSums(void) 
{ .... } 

Oczywiście zakłada to było rzeczywistą sytuację, a nie pytanie o rozmowę kwalifikacyjną lub pracę domową. Wciąż twierdzę, że jest to lepsze rozwiązanie w tych przypadkach, ale to tylko ja.:)

Powiązane problemy