Функции внутри функций в C
Я делаю код, похожий на этот:
#include <stdio.h>
double some_function( double x, double y)
{
double inner_function(double x)
{
// some code
return x*x;
}
double z;
z = inner_function(x);
return z+y;
}
int main(void)
{
printf("%f\n", some_function(2.0, 4.0));
return 0;
}
Это прекрасно компилируется в GCC (без предупреждений), но не компилируется в ICC.
ICC дает:
main.c(16): error: expected a ";"
{
^
main.c(21): warning #12: parsing restarts here after previous syntax error
double z;
^
main.c(22): error: identifier "z" is undefined
z = inner_function(x);
^
compilation aborted for main.c (code 2)
Что я делаю неправильно?
Спасибо.
(править) Извините за плохой пример. В моем исходном коде мне нужно делать это. Я использую численный интегратор GSL и имею что-то вроде:
double stuff(double a, double b)
{
struct parameters
{
double a, b;
};
double f(double x, void * params)
{
struct parameters p = (struct parameters *) params;
double a = p->a, b = b->b;
return some_expression_involving(a,b,x);
}
struct parameters par = {a,b};
integrate(&f, &par);
}
И у меня есть много функций с такой структурой: они являются результатом интеграции функций с большим количеством внешних параметров. А функции, которые реализуют численное интегрирование, должны получить указатель на функцию типа:
double f(double x, void * par)
Мне бы очень хотелось, чтобы функции были вложены таким образом, чтобы мой код не раздувался множеством и множеством функций. И я надеюсь, что смогу скомпилировать его с ICC, чтобы немного ускорить работу.
Ответы
Ответ 1
Все остальные предоставили вам канонический ответ: "Вложенные функции не разрешены в стандартном C" (поэтому любое их использование зависит от вашего компилятора).
Ваш пересмотренный пример:
double stuff(double a, double b)
{
struct parameters
{
double a, b;
};
double f(double x, void * params)
{
struct parameters p = (struct parameters *) params;
double a = p->a, b = b->b;
return some_expression_involving(a,b,x);
}
struct parameters par = {a,b};
return integrate(&f, &par); // return added!
}
Поскольку вы говорите, что функции, такие как интегратор, нуждаются в
double (*f)(double x, void * par);
Я не понимаю, почему вам действительно нужны вложенные функции. Я ожидал бы написать:
struct parameters
{
double a, b;
};
static double f(double x, void *params)
{
struct parameters p = (struct parameters *) params;
double a = p->a, b = b->b;
return some_expression_involving(a,b,x);
}
double stuff(double a, double b)
{
struct parameters par = { a, b };
return integrate(f, &par);
}
Приведенный выше код должен работать на C89 (если нет проблемы с инициализацией "par" ) или C99; эта версия кода предназначена только для C99, используя составной литерал для параметра (раздел 6.5.2.5 Компонентные литералы):
double stuff(double a, double b)
{
return integrate(f, &(struct parameters){a, b});
}
Шансы превосходны, что у вас есть только несколько вариантов типа "структурных параметров". Вам нужно предоставить отдельные (достаточно) значащие имена для различных функций - у вас может быть только одна функция, называемая "f
" для исходного файла.
Единственное предельное крошечное преимущество версии вложенной функции заключается в том, что вы можете быть уверены, что никакая другая функция, кроме stuff
, вызывает f
. Но, учитывая примерный код, это не главное преимущество; статическое определение f
означает, что никакая функция вне этого файла не может вызвать его, если не передана указатель на функцию.
Ответ 2
Вложенные функции доступны в качестве расширения языка в GCC, но они не являются частью стандартного языка, поэтому некоторые компиляторы не позволят им.
Ответ 3
C не имеет вложенных функций. Вложенные функции GCC являются расширением языка.
Ошибка выполнения в GCC является орфографической ошибкой. inner_funcion
должен быть inner_function
.
Ответ 4
Как уже упоминалось выше, внутренние функции не поддерживаются в C, однако внутренние классы могут использоваться на С++ для достижения подобной вещи. К сожалению, они немного громоздки в использовании, но это может быть вариант для вас, если вы не против компиляции как С++.
Неподтвержденный пример:
double some_function( double x, double y)
{
struct InnerFuncs
{
double inner_function(double x)
{
// some code
return x*x;
}
// put more functions here if you wish...
} inner;
double z;
z = inner.inner_function(x);
return z+y;
}
Обратите внимание, что этот ответ не должен подразумевать, что я считаю, что внутренние функции являются хорошей идеей в использовании, которое вы показали.
Год спустя:
С++ теперь позволяет использовать lambdas в качестве внутренних функций. В случае моего примера с игрушкой выше это выглядело бы так:
double some_function( double x, double y)
{
auto inner_function = [&]() { return x * x; }
double z;
z = inner_function ();
return z + y;
}
Обратите внимание, что локальная переменная x автоматически фиксируется внутри лямбда, что является очень приятной функцией.
Подробнее здесь: Что такое лямбда-выражение в С++ 11?
Ответ 5
Вы используете вложенные функции - C не поддерживает такие вещи.
Ответ 6
Это не действительный код C, внутренние функции не поддерживаются в C
Ответ 7
локальные определения функций внутри функции являются незаконными в C.
Ответ 8
Вложенные функции не являются частью стандартов C. Поэтому нет никакой гарантии, что он будет работать для всех компиляторов и определенно следует избегать.
Ответ 9
В случае, если вам интересно, как отключить расширения GCC и т.д.
Вы можете использовать флаг -ansi
, который по существу устанавливает стандарт на c89 и отключает функции GCC, которые несовместимы с ISO C90.
Для получения дополнительной информации см. docs. Проверьте флаг -std
.
Ответ 10
Я не эксперт, но я готов поспорить, что это либо явно не разрешено, либо undefined по спецификации C99, поэтому лучше всего держаться подальше от него.