Вложенная функция в C

97

Можем ли мы иметь вложенную функцию в C? Какая польза от вложенных функций? Если они существуют в C, отличается ли их реализация от компилятора к компилятору?

Сачин Чурасия
источник
1
Кажется, это дубликат: stackoverflow.com/questions/1348095/…
zoli2k
1
также stackoverflow.com/questions/666586/… и stackoverflow.com/questions/2256647/… и stackoverflow.com/questions/957592/… и другие взяты из stackoverflow.com/search?q=nested+functions+[c]
dmckee --- котенок экс-модератора

Ответы:

112

Вы не можете определить функцию внутри другой функции в стандарте C.

Вы можете объявить функцию внутри функции, но это не вложенная функция.

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

Джеймс МакНеллис
источник
36

Нет, их нет в C.

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

  1. Они позволяют функциональную декомпозицию, не загрязняя пространства имен. Вы можете определить одну общедоступную функцию, которая реализует некоторую сложную логику, полагаясь на одну или несколько вложенных функций, чтобы разбить проблему на более мелкие, логические части.
  2. В некоторых случаях они упрощают передачу параметров. Вложенная функция имеет доступ ко всем параметрам и некоторым или всем переменным в области действия внешней функции, поэтому внешней функции не нужно явно передавать кучу локального состояния во вложенную функцию.
Марсело Кантос
источник
21

Вложенные функции не являются частью ANSI C , однако, они являются частью Gnu C .

zoli2k
источник
Какое там значение, если они являются частью Gnu C
Sachin Chourasiya
4
@Sachin Помогает понять, почему код C с вложенными функциями может быть скомпилирован с помощью 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)
{
}
CB Bailey
источник
6
Если функция g объявлена ​​таким образом, какова будет ее область действия?
Сачин Чурасия,
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 ++
Вирджил
11
@Virgile - И в вопросе также конкретно говорится: «Разрешены ли вложенные функции на любом другом языке?». Ответ Джона мне помог.
www-0av-Com
3

Как ответили другие, стандартный C не поддерживает вложенные функции.

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

В C это можно сделать, поместив такие функции в отдельный исходный файл. Определите основную функцию как глобальную, а все остальные функции и переменные как статические . Теперь вне этого модуля видна только основная функция.

Паулил
источник
Если есть рекурсия outer-> nested-> outer-> nested, тогда будет два разных кадра int declared_in_outer, поэтому вы не можете просто поставить declared_in_outerкак статический глобальный.
Адриан Панасюк 04
1

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

В JavaScript, который является одним из самых известных из этих языков, могут быть вложенные функции (которые называются замыканиями):

  • Создавать методы класса в конструкторах объектов.
  • Для достижения функциональности частных членов класса вместе с сеттерами и геттерами.
  • Чтобы не загрязнять глобальное пространство имен (это, конечно, касается всех языков).

назвать несколько...

KyriakosSt
источник
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
AnArrayOfFunctions
источник
-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.
Нейт Элдридж
спасибо за ваш вклад. С тех пор я узнал, как правильно объявлять, определять и использовать функции. немного неловко оглядываться на>. <
midnightCoder
1
@midnightCoder: вы всегда можете удалить свой ответ :)
chqrlie