可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm making a code that is similar to this:
#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;
}
This compiles perfectly in GCC (with no warnings) but fails to compile in ICC.
ICC gives:
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)
What am I doing wrong?
Thanks.
(edit) Sorry for the poor example. In my original code I kinda need to do this stuff. I'm using a GSL numerical integrator and have something like:
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);
}
And I have lots of functions with this kind of structure: they are the result of an integration of a functions with lots of external parameters. And the functions that implements numerical integration must receive a pointer to a function of type:
double f(double x, void * par)
I would really like functions to be nested this way so my code doesn't bloat with lots and lots of functions. And I hope I could compile it with ICC to speed things a bit.
回答1:
Everybody else has given you the canonical answer "Nested functions are not allowed in standard C" (so any use of them depends on your compiler).
Your revised example is:
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!
}
Since you say that the functions such as the integrator need
double (*f)(double x, void * par);
I don't see why you really need nested functions at all. I would expect to write:
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);
}
The code above should work in C89 (unless there's an issue with initializing 'par' like that) or C99; this version of the code is for C99 only, using a compound literal for the parameter (section 6.5.2.5 Compound literals):
double stuff(double a, double b)
{
return integrate(f, &(struct parameters){a, b});
}
The chances are excellent that you have only a few variations on the 'struct parameters' type. You do need to provide separate (sufficiently) meaningful names for the various functions - you can only have one function called 'f
' per source file.
The only marginal, tiny benefit of the nested function version is that you can be sure that no other function than stuff
calls f
. But given the example code, that is not a major benefit; the static definition of f
means that no function outside this file can call it unless passed a pointer to the function.
回答2:
Nested functions are available as a language extension in GCC, but they are not part of the standard language, so some compilers will not allow them.
回答3:
C doesn't have nested functions. GCC's nested functions are an extension to the language.
Your runtime error in GCC is a spelling error. inner_funcion
should be inner_function
.
回答4:
As mentioned by many answers above, inner functions are not supported in C, however inner classes can be used in C++ to accomplish a similar thing. Unfortunately they are a bit unwieldy to use, but it might be an option for you if you don't mind compiling as C++.
Untested example:
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;
}
Note that this answer shouldn't imply that I think inner functions are a good idea in the usage you've shown.
Years-later edit:
C++ now allows us to use lambdas as inner functions. In the case of my toy example above, it would look much like this:
double some_function( double x, double y)
{
auto inner_function = [&]() { return x * x; }
double z;
z = inner_function ();
return z + y;
}
Note the local variable x is automatically captured inside of the lambda, which is a very nice feature.
More here: What is a lambda expression in C++11?
回答5:
You are using nested functions - C does not support such things.
回答6:
That is not a valid C code, inner functions are not supported in C
回答7:
local function definitions inside a function are illegal in C.
回答8:
Nested functions are not part of the C standards. There is therefore no guarantee that it will work for all compilers and should definitely be avoided.
回答9:
In the event you were wondering how to turn off GCC extensions and such.
You can use the -ansi
flag which essentially sets the standard to c89, and turns off GCC features which are incompatible with ISO C90.
See the docs for more information. Check out the -std
flag too.
回答10:
I'm not an expert, but I'm willing to bet this is either explicitly not allowed or undefined by the C99 spec, so it's probably best to stay away from it.