Funzione annidata in C


93

Possiamo avere una funzione annidata in C? Qual è l'uso delle funzioni annidate? Se esistono in C, la loro implementazione differisce da compilatore a compilatore?


1
Sembra essere un duplicato di: stackoverflow.com/questions/1348095/...
zoli2k

Risposte:



36

No, non esistono in C.

Sono usati in linguaggi come Pascal per (almeno) due motivi:

  1. Consentono la scomposizione funzionale senza inquinare i namespace. È possibile definire una singola funzione visibile pubblicamente che implementa una logica complessa facendo affidamento su una o più funzioni annidate per suddividere il problema in parti logiche più piccole.
  2. Semplificano il passaggio dei parametri in alcuni casi. Una funzione annidata ha accesso a tutti i parametri e ad alcune o tutte le variabili nell'ambito della funzione esterna, quindi la funzione esterna non deve passare esplicitamente una pila di stati locali alla funzione annidata.

21

Funzioni nidificate non sono una parte di ANSI C , tuttavia, fanno parte di Gnu C .


Che significato hanno se fanno parte di Gnu C
Sachin Chourasiya

4
@Sachin Aiuta a capire perché il codice C con funzioni annidate può essere compilato con gcc. L'informazione ha valore educativo. Inoltre, la domanda non specifica se è limitata solo a C89, C99 o GNU C
zoli2k

4
Altri linguaggi supportati da GCC li hanno (ADA e Pascal che conosco), quindi è probabile che sia stato facile da aggiungere all'implementazione C o che sia stato aggiunto a C per preparare in preparazione per i linguaggi di supporto che richiederli.
nategoose

MATLAB ha anche funzioni annidate.
mikeTronix

17

No, non puoi avere una funzione annidata in C. Il più vicino che puoi arrivare è dichiarare una funzione all'interno della definizione di un'altra funzione. La definizione di quella funzione, però, deve apparire al di fuori di qualsiasi altro corpo di funzione.

Per esempio

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

    // Call g
    g();
}

// Definition of g
void g(void)
{
}

6
Se la funzione g viene dichiarata in questo modo, quale sarà il suo ambito?
Sachin Chourasiya

6
La dichiarazione ha lo scope come qualsiasi altra dichiarazione, quindi in questo caso fino alla fine della funzione. Ovviamente, una volta che la definizione di gè visibile più avanti nel file, quella dichiarazione è nell'ambito del resto dell'unità di traduzione. Inoltre puoi chiamare funzioni in C senza una dichiarazione visibile nell'ambito anche se non è consigliabile.
CB Bailey

5

Lo dico perché molte persone che codificano in C ora usano compilatori C ++ (come Visual C ++ e Keil uVision) per farlo, quindi potresti essere in grado di usarlo ...

Sebbene non sia ancora consentito in C, se stai utilizzando C ++, puoi ottenere lo stesso effetto con le funzioni lambda introdotte in C ++ 11:

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

    g();
}

4
La domanda riguardava specificamente C, non C ++
Virgile

11
@ Virgile - E la domanda ha anche affermato specificamente "Le funzioni nidificate sono consentite in qualsiasi altra lingua?". La risposta di Jon mi ha aiutato.
www-0av-Com

3

Come altri hanno risposto, lo standard C non supporta le funzioni annidate.

Le funzioni annidate vengono utilizzate in alcuni linguaggi per racchiudere più funzioni e variabili in un contenitore (la funzione esterna) in modo che le singole funzioni (esclusa la funzione esterna) e le variabili non siano viste dall'esterno.

In C , questo può essere fatto inserendo tali funzioni in un file sorgente separato. Definisci la funzione principale come globale e tutte le altre funzioni e variabili come statiche . Ora solo la funzione principale è visibile all'esterno di questo modulo.


Se c'è la ricorsione outer-> nested-> outer-> nested, allora ci sarebbero due frame diversi che tengono int declared_in_outer, quindi non puoi semplicemente metterlo declared_in_outercome globale statico.
Adrian Panasiuk

1

Per rispondere alla tua seconda domanda, esistono linguaggi che consentono la definizione di funzioni annidate (un elenco può essere trovato qui: annidato-funzioni-lingua-elenco-wikipedia ).

In JavaScript, che è uno dei più famosi di quei linguaggi, una delle funzioni annidate (che sono chiamate chiusure) sono:

  • Per creare metodi di classe nei costruttori di oggetti.
  • Per ottenere la funzionalità dei membri della classe privata insieme a setter e getter.
  • Non inquinare lo spazio dei nomi globale (che vale per ogni lingua, ovviamente).

per dirne alcuni...


0

Oppure puoi essere intelligente e utilizzare il preprocessore a tuo vantaggio ( 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

-1

non è questa una funzione annidata in C? (la funzione displayAccounts ())

So che avrei potuto definire la funzione in modo diverso e passare variabili e cosa no, ma comunque funziona bene poiché avevo bisogno di stampare gli account più volte.

(beccuccio tratto da un compito scolastico) ...

//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;
}

4
Non è lo standard legale C. Se funziona con il tuo compilatore, è perché il tuo compilatore ha fornito un'estensione al linguaggio C standard; in un certo senso il tuo compilatore sta compilando una lingua diversa, che è, in senso stretto, non C.
Nate Eldredge

Grazie per il tuo contributo. Da allora ho imparato il modo corretto di dichiarare, definire e utilizzare le funzioni. questo è un po 'imbarazzante a ripensarci>. <
mezzanotteCoder

1
@midnightCoder: puoi sempre cancellare la tua risposta :)
chqrlie
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.