Função aninhada em C

93

Podemos ter uma função aninhada em C? Qual é o uso de funções aninhadas? Se eles existem em C, sua implementação difere de compilador para compilador?

Sachin Chourasiya
fonte

Respostas:

108

Você não pode definir uma função dentro de outra função no padrão C.

Você pode declarar uma função dentro de uma função, mas não é uma função aninhada.

gcc tem uma extensão de linguagem que permite funções aninhadas . Eles não são padronizados e, como tais, são totalmente dependentes do compilador.

James McNellis
fonte
36

Não, eles não existem em C.

Eles são usados ​​em linguagens como Pascal por (pelo menos) dois motivos:

  1. Eles permitem a decomposição funcional sem poluir os namespaces. Você pode definir uma única função publicamente visível que implemente alguma lógica complexa, contando com uma ou mais funções aninhadas para quebrar o problema em partes lógicas menores.
  2. Eles simplificam a passagem de parâmetros em alguns casos. Uma função aninhada tem acesso a todos os parâmetros e algumas ou todas as variáveis ​​no escopo da função externa, portanto, a função externa não precisa passar explicitamente uma pilha de estados locais para a função aninhada.
Marcelo Cantos
fonte
21

Aninhados funções não são uma parte de ANSI C , no entanto, eles fazem parte de GNU C .

zoli2k
fonte
O que há significado se eles fazem parte do Gnu C
Sachin Chourasiya
4
@Sachin Ajuda a perceber porque o código C com funções aninhadas pode ser compilado com gcc. A informação tem valor educacional. Além disso, a pergunta não especifica se está limitada apenas a C89, C99 ou GNU C
zoli2k
4
Outras linguagens suportadas pelo GCC os têm (ADA e Pascal que eu conheço), então é provável que ou foi fácil adicionar à implementação C ou que foi adicionado ao C a fim de preparar para linguagens de suporte que exigi-los.
nategoose
O MATLAB também possui funções aninhadas.
mikeTronix de
17

Não, você não pode ter uma função aninhada em C. O mais próximo que você pode chegar é declarar uma função dentro da definição de outra função. A definição dessa função deve aparecer fora de qualquer outro corpo de função, no entanto.

Por exemplo

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

    // Call g
    g();
}

// Definition of g
void g(void)
{
}
CB Bailey
fonte
6
Se a função g for declarada dessa forma, qual será seu escopo?
Sachin Chourasiya,
6
A declaração tem o escopo definido como qualquer outra declaração, portanto, neste caso, até o final da função. É claro que, uma vez que a definição de gesteja visível posteriormente no arquivo, essa declaração estará no escopo para o resto da unidade de tradução. Além disso, você pode chamar funções em C sem uma declaração visível no escopo, mesmo que não seja aconselhável.
CB Bailey,
5

Menciono isso porque muitas pessoas que codificam em C agora estão usando compiladores C ++ (como Visual C ++ e Keil uVision) para fazer isso, então você pode fazer uso disso ...

Embora ainda não seja permitido em C, se você estiver usando C ++, poderá obter o mesmo efeito com as funções lambda introduzidas em C ++ 11:

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

    g();
}
Jon Green
fonte
4
A pergunta era especificamente sobre C, não C ++
Virgile
11
@Virgile - E a questão também afirmava especificamente "As funções aninhadas são permitidas em alguma outra linguagem?". A resposta de Jon me ajudou.
www-0av-Com
3

Como outros responderam, C padrão não suporta funções aninhadas.

Funções aninhadas são usadas em algumas linguagens para incluir várias funções e variáveis ​​em um contêiner (a função externa) para que as funções individuais (excluindo a função externa) e as variáveis ​​não sejam vistas de fora.

Em C , isso pode ser feito colocando essas funções em um arquivo de origem separado. Defina a função principal como global e todas as outras funções e variáveis ​​como estáticas . Agora, apenas a função principal é visível fora deste módulo.

PauliL
fonte
Se houver recursão outer-> nested-> outer-> nested, então haveria dois quadros diferentes segurando int declared_in_outer, então você não pode simplesmente colocar declared_in_outercomo um global estático.
Adrian Panasiuk
1

Para responder à sua segunda pergunta, existem linguagens que permitem definir funções aninhadas (uma lista pode ser encontrada aqui: nested-functions-language-list-wikipedia ).

Em JavaScript, que é uma das mais famosas dessas linguagens, uma das funções aninhadas (que são chamadas de fechamentos) são:

  • Para criar métodos de classe em construtores de objetos.
  • Para obter a funcionalidade de membros da classe privada junto com setters e getters.
  • Para não poluir o namespace global (isso vale para todos os idiomas, é claro).

para nomear alguns...

kyriakosSt
fonte
0

Ou você pode ser esperto e usar o pré-processador a seu favor ( 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
fonte
-1

esta não é uma função aninhada em C? (a função displayAccounts ())

Eu sei que poderia ter definido a função de forma diferente e passado variáveis ​​e o que não, mas de qualquer forma funciona bem, pois precisei imprimir as contas várias vezes.

(fragmento tirado de um trabalho escolar) ...

//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
fonte
4
Não é o padrão C legal. Se funcionar com o seu compilador, é porque o seu compilador forneceu uma extensão para a linguagem C padrão; em certo sentido, seu compilador está compilando uma linguagem diferente, que é, estritamente falando, não C.
Nate Eldredge
Obrigdo por sua contribuição. Desde então, aprendi a maneira adequada de declarar, definir e usar funções. é um pouco embaraçoso olhar para trás>. <
midnightCoder
1
@midnightCoder: Você sempre pode excluir sua resposta :)
chqrlie