Вкладена функція в C


93

Чи можемо ми мати вкладену функцію в C? Що таке вкладені функції? Якщо вони існують в C, чи відрізняється їх реалізація від компілятора до компілятора?


1
Здається, дублікат: stackoverflow.com/questions/1348095 / ...
zoli2k

Відповіді:


108

Ви не можете визначити функцію в межах іншої функції за стандартом C.

Ви можете оголосити функцію всередині функції, але це не вкладена функція.

gcc має розширення мови, яке дозволяє вкладені функції . Вони нестандартні і як такі повністю залежать від компілятора.


36

Ні, вони не існують у C.

Вони використовуються такими мовами, як Паскаль, з (принаймні) двох причин:

  1. Вони дозволяють функціонально розкладати без забруднення просторів імен. Ви можете визначити одну загальнодоступну функцію, яка реалізує якусь складну логіку, спираючись на одну або кілька вкладених функцій, щоб розбити проблему на менші логічні частини.
  2. У деяких випадках вони спрощують передачу параметрів. Вкладена функція має доступ до всіх параметрів та деяких або всіх змінних в області зовнішньої функції, тому зовнішня функція не повинна явно передавати купу локального стану у вкладену функцію.

21

Вкладені функції не є частиною ANSI C , проте, вони є частиною Gnu C .


Яке значення, якщо вони є частиною Gnu C
Sachin Chourasiya

4
@Sachin Допомагає зрозуміти, чому код С із вкладеними функціями можна компілювати за допомогою gcc. Інформація має освітнє значення. Більше того, питання не вказує, чи обмежується воно лише C89, C99 або GNU C
zoli2k

4
В інших мовах, які підтримуються GCC, вони є (ADA та Pascal, яких я знаю), тому, цілком ймовірно, що їх було легко додати до реалізації C, або що вони були додані до C, щоб підготуватися до підтримуючих мов, які вимагати їх.
nategoose

MATLAB також має вкладені функції.
mikeTronix

17

Ні, ви не можете мати вкладену функцію в C. Найближче, до чого ви можете підійти, - це оголошення функції у визначенні іншої функції. Визначення цієї функції, однак, має з'являтися поза будь-яким іншим тілом функції.

Напр

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

    // Call g
    g();
}

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

6
Якщо функцію g оголошено таким чином, то яким буде її обсяг?
Sachin Chourasiya

6
Оголошення масштабується, як і будь-яке інше оголошення, тому в цьому випадку до кінця функції. Звичайно, як тільки визначення "" gбуде видно пізніше у файлі, це оголошення буде застосовано до решти блоку перекладу. Крім того, ви можете викликати функції на C без видимого оголошення в області дії, навіть якщо це недоцільно.
CB Bailey

5

Я згадую це, оскільки багато людей, що кодують на C, зараз використовують компілятори C ++ (такі як Visual C ++ та Keil uVision), щоб ви могли це використовувати ...

Хоча це ще не дозволено в C, якщо ви використовуєте C ++, ви можете досягти того ж ефекту за допомогою лямбда-функцій, представлених в C ++ 11:

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

    g();
}

4
Питання саме стосувалося C, а не C ++
Virgile

11
@Virgile - І в запитанні також було конкретно зазначено "Чи дозволені вкладені функції будь-якою іншою мовою?". Відповідь Джона мені допомогла.
www-0av-Com

3

Як відповіли інші, стандарт C не підтримує вкладені функції.

Вкладені функції використовуються в деяких мовах для укладання декількох функцій та змінних у контейнер (зовнішня функція), так що окремі функції (крім зовнішньої функції) та змінні не видно ззовні.

У C це можна зробити, помістивши такі функції в окремий вихідний файл. Визначте основну функцію як глобальну, а всі інші функції та змінні як статичну . Тепер поза цим модулем видно лише основну функцію.


Якщо є рекурсія outer-> nested-> outer-> nested, тоді було б два різних кадру, утримуючи int declared_in_outer, тому ви не можете просто поставити declared_in_outerяк статичний глобальний.
Адріан Панасюк

1

Щоб відповісти на ваше друге запитання, є мови, які дозволяють визначати вкладені функції (список можна знайти тут: nested-functions-language-list-wikipedia ).

У JavaScript, який є однією з найвідоміших з цих мов, можливо, вкладеними функціями (які називаються закриттями) є:

  • Створювати методи класів у конструкторах об'єктів.
  • Щоб досягти функціональності приватних членів класу разом із сетерами та геттерами.
  • Не забруднювати глобальний простір імен (звичайно, це стосується кожної мови).

назвати декілька...


0

Або ви можете бути розумними з цим і використовувати препроцесор на свою користь ( 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

це не вкладена функція в C? (функція displayAccounts ())

Я знаю, що міг визначити функцію інакше і передавати змінні, а що ні, але все одно працює добре, оскільки мені потрібно було надрукувати рахунки кілька разів.

(фрагмент узятий із шкільного завдання) ...

//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
Це не юридичний стандарт C. Якщо він працює з вашим компілятором, це тому, що ваш компілятор надав розширення до стандартної мови C; у якомусь сенсі ваш компілятор компілює іншу мову, яка, строго кажучи, не C.
Nate Eldredge

дякую за ваш внесок. З тих пір я навчився правильного способу декларування, визначення та використання функцій. це трохи соромно озиратися назад>. <
midnightCoder

1
@midnightCoder: Ви завжди можете видалити свою відповідь :)
chqrlie
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.