2015-02-28 19 views
10

Oto prosta funkcja z jednym int parametru:Przetwarzanie int (x) parametr

void f(int x) {} 

f(42); 

A oto kolejna funkcja z jednym int parametru:

void g(int(x)) {} 

g(42); 

Teraz nam określić x do być typu:

typedef int x; 
void h(int(x)) {} 

h(42); 
// warning: passing argument 1 of ‘h’ makes pointer from integer without a cast 

(To jest zachowanie obserwuję z gcc 4.8.2)

W jaki sposób scenarzyści zajmują się tą sytuacją?

Wygląda na to, że klasyczny rurociąg Lexer -> Parser -> Semantic Checker -> ... nie działa tutaj.

+5

Och, Fred, znowu jesteś w najbardziej irytującej analizie. Tak, to ten sam mechanizm. I masz rację, wiedza płynie z powrotem w rurociągu. –

+0

Ktoś usunął tag C++. Odkładam to. Czy chcesz to być C lub C++ @FredOverflow. –

+1

Lexer wysyła symbol x -> analizator składni znający znaczenie syboli znajduje potencjalne reguły gramatyczne (i ma wątpliwości, stosuje najbardziej irytującą ** parsę **) -> sprawdzian semantyczny szuka potencjalnych konwersji typów. Nie wiem, co nie powinno działać w klasycznym przewodniku ...? – Christophe

Odpowiedz

12

pan skutecznie zdefiniowany h jak:

void h(int(int)) {} 

Parametr jest interpretowane jako bezimiennego wskaźnika funkcji, która pobiera int i zwraca int. Kiedy próbujesz przekazać do niego 42, kompilator narzeka, że ​​próbujesz utworzyć wskaźnik funkcji z liczby całkowitej.

Myślę, że to, o co prosisz, to w jaki sposób kompilatory obsługują (nienazwane) typy wskaźników funkcji i ich możliwie niejednoznaczne analizy. Twoje pytanie jest związane z the most vexing parse w C++.

Tam zdecydowali, że ilekroć pomiędzy typem wskaźnika funkcji i niejednoznacznym sposobem analizowania występuje niejednoznaczność, zostanie to zinterpretowane jako wskaźnik funkcji. Zrobili tak, ponieważ istnieją inne sposoby rozróżniania, gdy nie chcesz, aby był wskaźnikiem funkcji (np. - otaczaj go w nawiasach, używaj {} składni inicjalizatora, itp.).

dojazd do specyfiki jak pisarz parser może sobie z tego parsowania, oto leksykalny analizator i gramatyka dla C11: http://quut.com/c/ANSI-C-grammar-l-2011.html W przykładzie przed typedef, x będzie IDENTIFIER żeton natomiast później będzie to TYPEDEF_NAME token, ponieważ analizator jest informowany za pomocą tabeli symboli, że x jest teraz typem. W tym konkretnym przypadku parsowanie jest wtedy jednoznaczne. "Odniesienie do rurociągu", o którym zdaje się, że się powołuje, występuje w tym przypadku poprzez tabelę symboli, gdzie analizator leksykalny jest informowany o kontekście przez wyższe poziomy, które wpływają na jego wynik w miarę rozwoju kompilacji.

EDIT: Thesethreearticles, znaleziona przez PO, opisać ten problem i jak to jest rozwiązane przez niektórych parserami C/kompilatory bardzo ładnie. Zasadniczo prawie można określić gramatykę bez kontekstu, która akceptuje/generuje prawną składnię C. Po wprowadzeniu tabeli wyszukiwania o ustalonym zakresie, która pozwala analizatorowi leksykalnemu na odpowiednie rozróżnienie identyfikatorów od nazw typef, następnie CFG [i, co ważniejsze, parser LALR (1) (np. Yacc generowany)], który akceptuje/generuje tylko legalny C można podać składnię.

Oto jeszcze straszniejsze przykładem niż OP:

typedef int x; 

int main() { x x = 5; return x; } /* crazily enough this is legal C syntax and a well formed C program */ 
+0

Nie powinien wydawać ostrzeżenia, ale błąd, ponieważ nie jest niejawna konwersja do 'int (*)()'. – Christophe

+1

@ Christophe, myślę, że C pozwala zrobić to bez wyraźnej obsady. – chris

+0

OK! Spojrzałem na reklamy w okularach C++! – Christophe

6

Po wprowadzeniu typedef

typedef int x; 

funkcja ma następującą definicję

void h(int(int)) {} 

że jest jego parametrem jest zadeklarowana jako o typie funkcji int(int) dostosowanym do wskaźnika do funkcji jon.

wywołać funkcję dostarczania liczbę całkowitą:

h(42); 

Nie ma niejawna konwersja z liczby całkowitej funkcjonować wskaźnik.

nie widzę problemu z

Wydaje klasyczny rurociąg Lexer -> Parser -> Semantic Checker -> ... nie działa tutaj.

Parametr zastępuje typedef.
x ma atrybut kompilatora typu. Więc uważa, że ​​rekord taki jak

type-specifier h(type-specifier(type-name)) {} 
+3

Myślę, że Fred pyta o użycie informacji nieskryptycznych w analizie, tj. Jak wiedza o naturze "x" wpływa na parsowanie. –

+0

@Cheers and hth. - Alf. Zaktualizowałem swój post. –

+1

Dzięki Vlad. Myślę jednak, że nie zgadzam się z twoim wnioskiem dotyczącym substytucji. Przynajmniej myślę, że jeśli jest to poprawne, to norma byłaby miła. –