Co oznaczają nawiasy wokół nazwy funkcji?

214

W jednym z moich plików źródłowych projektu znalazłem definicję funkcji C:

int (foo) (int *bar)
{
    return foo (bar);
}

Uwaga: obok nie ma gwiazdki foo, więc nie jest wskaźnikiem funkcji. Albo to jest? Co się tutaj dzieje z połączeniem rekurencyjnym?

użytkownik1859094
źródło
7
Nie, to nie jest wskaźnik funkcji - to wciąż zwykła funkcja o nazwie foo.
Nemanja Boric
Czy to pełna funkcja?
asheeshr
2
czy masz dowody, że ta funkcja jest używana w przydatnym kontekście?
moooeeeep
1
... wygląda jak sztuczna funkcja, która być może właśnie została napisana, aby sprawdzić, czy kompiluje się w istniejącym źródle i powinna zostać usunięta. Usunęłbym to (jeśli tak właśnie działa ta funkcja), ponieważ w najlepszym wypadku będzie to pętla nieskończona (nie jestem pewien, czy kompilator C może zoptymalizować to wywołanie skoku), w najgorszym przypadku przepełnienia stosu.
hyde
3
Nawiasy w deklaracjach C pomagają nadać językowi niejednoznaczność. Szybko, co to jest a(b);? Deklaracja bjako zmiennej typu a? Lub wezwanie do działania az argumentem b? Różnica jest składniowa i nie możesz wiedzieć, w jaki sposób ją parsować, nie sprawdzając informacji o deklaracji a; tzn. są to nawiasy wywołujące funkcję Postfiks lub opcjonalne nawiasy wokół deklaratora.
Kaz

Odpowiedzi:

329

Wobec braku jakichkolwiek działań preprocesora foopodpis jest równoważny

int foo (int *bar)

Jedynym kontekstem, w którym widziałem ludzi umieszczających pozornie niepotrzebne nawiasy wokół nazw funkcji, jest to, że istnieje zarówno funkcja, jak i makro podobne do funkcji o tej samej nazwie, a programista chce zapobiec ekspansji makr.

Ta praktyka może początkowo wydawać się trochę dziwna, ale biblioteka C stanowi precedens, udostępniając niektóre makra i funkcje o identycznych nazwach .

Jedną z takich par funkcji / makr jest isdigit(). Biblioteka może to zdefiniować w następujący sposób:

/* the macro */
#define isdigit(c) ...

/* the function */
int (isdigit)(int c) /* avoid the macro through the use of parentheses */
{
  return isdigit(c); /* use the macro */
}

Twoja funkcja wygląda prawie identycznie jak powyżej, więc podejrzewam, że tak dzieje się również w twoim kodzie.

NPE
źródło
2
Tak może być i tutaj; Nie szukałem makr ... I nie wiedziałem, że rozwijanie makr nie odbywa się w nawiasach, Dziękujemy za zwrócenie na to uwagi!
user1859094,
13
@ user1859094: Przy drugim spojrzeniu prawie na pewno dzieje się to w kodzie. foo(bar)Wewnątrz funkcji jest za pomocą odpowiedniego makro.
NPE
78
@ user1859094 interpretacja makr odbywa się w nawiasach, ale interpretacja makra podobnego do funkcji ma miejsce tylko wtedy, gdy następny token jest lewym nawiasiem (C99, 6.10.3§10), a zatem foo (int* bar)zostałby zastąpiony, ale nie (foo) (int *bar)(następny token po foojest ))
Virgile,
4
Jak można by wywołać taką funkcję? Czy nazwałbyś to również nawiasami? Na przykład, czy to zadziała (isdigit)(5):?
gcochard
4
@Greg: Racja, właśnie tak to nazwałbyś.
NPE
37

Nawiasy nie zmieniają deklaracji - nadal definiuje zwykłą funkcję o nazwie foo.

Powodem ich użycia jest prawie na pewno dlatego, że istnieje makro funkcyjne o nazwie foozdefiniowane:

#define foo(x) ...

Użycie (foo)w deklaracji funkcji zapobiega rozwinięciu tego makra w tym miejscu. Prawdopodobnie dzieje się tak, że funkcja foo()jest definiowana, a jej ciało jest rozszerzane z makra podobnego do funkcji foo.

caf
źródło
5
Niezła dedukcja (choć użycie nawiasów w tym celu powinno podlegać karze).
ugoren
3
@ugoren: używanie parens wokół nazwy funkcji jest jedynym sposobem, aby zapobiec rozszerzeniu makra dla makra podobnego do funkcji. Czasami jest to niezbędne narzędzie.
Michael Burr
7
@MichaelBurr, istnieje również opcja nie posiadania makra i funkcji o tej samej nazwie. Wiem, że nie zawsze możesz kontrolować wszystko, ale jeśli osiągniesz to rozwiązanie, powiedziałbym, że coś jest bardzo nie tak.
ugoren
-3

Nawiasy są bez znaczenia.
Wyświetlany kod jest niczym innym jak nieskończoną rekurencją.

Podczas definiowania wskaźnika funkcji czasami widać dziwne nawiasy, które coś znaczą. Ale tutaj tak nie jest.

ugoren
źródło
6
Najwyraźniej nie; nawiasy uniemożliwiają rozwój makr. Zobacz zaakceptowaną odpowiedź.
Kevin
12
@Kevin, Moja odpowiedź dotyczy pokazanego kodu i jest dla niego poprawna. W prawie każdym pytaniu C tutaj, przyjęcie nieznanych definicji preprocesora może zmienić wszystko. W tym przypadku odpowiedzi, które uważają, że preprocesor są rzeczywiście lepsze, ale to nie czyni mojej błędnej.
ugoren