Zagnieżdżona funkcja w C

97

Czy możemy mieć funkcję zagnieżdżoną w C? Jaki jest pożytek z funkcji zagnieżdżonych? Jeśli istnieją w C, czy ich implementacja różni się od kompilatora do kompilatora?

Sachin Chourasiya
źródło

Odpowiedzi:

36

Nie, nie istnieją w C.

Są używane w językach takich jak Pascal z (co najmniej) dwóch powodów:

  1. Pozwalają na funkcjonalną dekompozycję bez zanieczyszczania przestrzeni nazw. Można zdefiniować pojedynczą publicznie widoczną funkcję, która implementuje złożoną logikę, polegając na jednej lub większej liczbie funkcji zagnieżdżonych w celu rozbicia problemu na mniejsze, logiczne części.
  2. W niektórych przypadkach upraszczają przekazywanie parametrów. Funkcja zagnieżdżona ma dostęp do wszystkich parametrów i niektórych lub wszystkich zmiennych w zakresie funkcji zewnętrznej, więc funkcja zewnętrzna nie musi jawnie przekazywać stosu stanu lokalnego do funkcji zagnieżdżonej.
Marcelo Cantos
źródło
21

Funkcje zagnieżdżone nie są częścią ANSI C , jednak są one częścią GNU C .

zoli2k
źródło
Jakie ma znaczenie, jeśli są częścią Gnu C
Sachin Chourasiya
4
@Sachin Pomaga zrozumieć, dlaczego kod C z zagnieżdżonymi funkcjami można skompilować za pomocą gcc. Informacje mają wartość edukacyjną. Co więcej, pytanie nie precyzuje, czy jest ograniczone tylko do C89, C99 lub GNU C
zoli2k
4
Inne języki obsługiwane przez GCC mają je (o których wiem, ADA i Pascal), więc jest prawdopodobne, że albo było to łatwe do dodania do implementacji C, albo że zostało dodane do C w celu przygotowania do obsługi języków, które wymagają ich.
nategoose
MATLAB ma również funkcje zagnieżdżone.
mikeTronix,
17

Nie, nie możesz mieć funkcji zagnieżdżonej w C. Najbliższe możliwe jest zadeklarowanie funkcji wewnątrz definicji innej funkcji. Definicja tej funkcji musi jednak pojawić się poza jakimkolwiek innym ciałem funkcji.

Na przykład

void f(void)
{
    // Declare a function called g
    void g(void);

    // Call g
    g();
}

// Definition of g
void g(void)
{
}
CB Bailey
źródło
6
Jeśli funkcja g zostanie zadeklarowana w ten sposób, to jaki będzie jej zakres?
Sachin Chourasiya
6
Deklaracja jest objęta zakresem jak każda inna deklaracja, a więc w tym przypadku do końca funkcji. Oczywiście, gdy definicja gjest widoczna później w pliku, deklaracja ta jest objęta zakresem pozostałej części jednostki tłumaczeniowej. Poza ty może wywoływać funkcje w C bez widocznego deklaracji w zakresie, nawet jeśli nie jest to wskazane.
CB Bailey,
5

Wspominam o tym, ponieważ wiele osób kodujących w C korzysta teraz z kompilatorów C ++ (takich jak Visual C ++ i Keil uVision), aby to zrobić, więc możesz być w stanie wykorzystać to ...

Chociaż nie jest to jeszcze dozwolone w C, jeśli używasz C ++, możesz osiągnąć ten sam efekt za pomocą funkcji lambda wprowadzonych w C ++ 11:

void f()
{
    auto g = [] () { /* Some functionality */ }

    g();
}
Jon Green
źródło
4
Pytanie dotyczyło języka C, a nie C ++
Virgile
11
@Virgile - I pytanie również wyraźnie brzmi: „Czy funkcje zagnieżdżone są dozwolone w jakimkolwiek innym języku?”. Odpowiedź Jona pomogła mi.
www-0av-Com
3

Jak odpowiedzieli inni, standardowa C nie obsługuje funkcji zagnieżdżonych.

Funkcje zagnieżdżone są używane w niektórych językach do umieszczania wielu funkcji i zmiennych w kontenerze (funkcja zewnętrzna), dzięki czemu poszczególne funkcje (z wyjątkiem funkcji zewnętrznej) i zmienne nie są widoczne z zewnątrz.

W C można to zrobić, umieszczając takie funkcje w oddzielnym pliku źródłowym. Zdefiniuj główną funkcję jako globalną, a wszystkie inne funkcje i zmienne jako statyczne . Teraz tylko główna funkcja jest widoczna poza tym modułem.

PauliL
źródło
Jeśli istnieje rekurencja outer-> nested-> outer-> nested, to będą dwie różne ramki int declared_in_outer, więc nie możesz po prostu ustawić declared_in_outerjako statycznej globalnej.
Adrian Panasiuk
1

Odpowiadając na drugie pytanie, istnieją języki, które pozwalają na definiowanie funkcji zagnieżdżonych (lista znajduje się tutaj: nested-functions-language-list-wikipedia ).

W JavaScript, który jest jednym z najbardziej znanych języków, jedną z funkcji zagnieżdżonych (nazywanych domknięciami) są:

  • Tworzenie metod klasowych w konstruktorach obiektów.
  • Aby osiągnąć funkcjonalność członków klasy prywatnej wraz z ustawiającymi i pobierającymi.
  • Nie zanieczyszczać globalnej przestrzeni nazw (dotyczy to oczywiście każdego języka).

by wymienić tylko kilka...

kyriakosSt
źródło
0

Lub możesz być sprytny i wykorzystać preprocesor na swoją korzyść ( source.c):

#ifndef FIRSTPASS
#include <stdio.h>

//here comes your "nested" definitions
#define FIRSTPASS
#include "source.c"
#undef FIRSTPASS

main(){
#else
    int global = 2;
    int func() {printf("%d\n", global);}
#endif
#ifndef FIRSTPASS
    func();}
#endif
AnArrayOfFunctions
źródło
-1

czy to nie jest funkcja zagnieżdżona w C? (funkcja displayAccounts ())

Wiem, że mogłem zdefiniować funkcję inaczej i przekazywać zmienne, a co nie, ale i tak działa dobrze, ponieważ musiałem wielokrotnie drukować konta.

(wycinek pobrany z zadania szkolnego) ...

//function 'main' that executes the program.
int main(void)
{
    int customerArray[3][3] = {{1, 1000, 600}, {2, 5000, 2500}, {3, 10000, 2000}};  //multidimensional customer data array.
    int x, y;      //counters for the multidimensional customer array.
    char inquiry;  //variable used to store input from user ('y' or 'n' response on whether or not a recession is present).

    //function 'displayAccounts' displays the current status of accounts when called.
    void displayAccounts(void)
    {
        puts("\t\tBank Of Despair\n\nCustomer List:\n--------------");
        puts("Account #    Credit Limit\t  Balance\n---------    ------------\t  -------");
        for(x = 0; x <= 2; x++)
        {
            for(y = 0; y <= 2; y++)
                printf("%9d\t", customerArray[x][y]);
            puts("\n");
        }
    }

    displayAccounts();  //prints accounts to console.
    printf("Is there currently a recession (y or n)? ");


//...

    return 0;
}
midnightCoder
źródło
4
Nie jest to norma prawna C. Jeśli to działa z twoim kompilatorem, to dlatego, że twój kompilator dostarczył rozszerzenie standardowego języka C; w pewnym sensie twój kompilator kompiluje inny język, który, ściśle rzecz biorąc, nie jest językiem C.
Nate Eldredge Kwietnia
dziękuję za wkład. Od tego czasu nauczyłem się prawidłowego sposobu deklarowania, definiowania i używania funkcji. to trochę zawstydzające patrzeć wstecz>. <
midnightCoder
1
@midnightCoder: Zawsze możesz usunąć swoją odpowiedź :)
chqrlie