Why are nested functions not supported by the C standard?

It doesn't seem like it would be too hard to implement in an assembly.

gcc also has a flag (-fnested-functions) to enable their use.

+11
c function standards
Aug 28 '09 at 16:25
source share
10 answers

It turns out that in fact they are not so easy to implement correctly.

Should an internal function have access to scope variables contained? If not, it makes no sense to invest in it; just make it static (to limit the visibility of the translation unit in it) and add the comment "This is a helper function used only by myfunc ()."

If you want to access the scope variables contained in it, you basically force it to create closures (the alternative restricts what you can do with nested functions sufficient to make them useless). I think GCC actually does this by creating (at runtime) a unique thunk for each call to the contained function, which sets the context pointer and then calls the nested function. This ultimately is more of an Icky hack, and something that some perfectly reasonable implementations cannot do (for example, on a system that prohibits write-write memory — which many modern OSs do for security reasons). The only reasonable way to make it work as a whole is to make all function pointers carry around a hidden context argument and all functions to accept it (because in the general case you don't know when you call it a closure or an open function). This is impractical to require in C for both technical and cultural reasons, so we adhere to the possibility of using explicit context pointers to fake closures instead of nesting functions or using a higher level language that has the infrastructure necessary to do this correctly.

+11
Aug 28 '09 at 17:45
source share

I would like to quote something from BDFL (Guido van Rossum):

This is because the definitions of nested functions do not have access to the local variables of the surrounding block - only for the global containing module. This is done so that global searches must go through a chain of dictionaries - as in C, there are only two nested areas: local and global (and, outside this, built-in). Therefore, nested functions have limited use. This was a deliberate decision, based on experience with languages ​​that allowed such as Pascal and both Algols - the code, too, many nested areas are approximately as readable as the code with too much GOTO.

The emphasis is mine.

I believe that it referenced a nested scope in Python (and as David points out in the comments, this has been since 1993, and Python now supports fully nested functions), but I think the operator is still applicable.

Another part of this may be closure .

If you have a function like this code like C:

(*int()) foo() { int x = 5; int bar() { x = x + 1; return x; } return &bar; } 

If you use bar in some callback, what happens with x? Is this well defined in many newer higher-level languages, but does AFAIK have no clearly defined way to track that x in C - does bar returns 6 each time, or does consecutive calls on bar return increment values? This could potentially add a whole new level of complexity to C with a relatively simple definition.

+9
Aug 28 '09 at 16:47
source share

See C FAQ 20.24 and the GCC manual for potential problems:

If you try to call a nested function through your address after the containing function has exited, all hell will break. If you try to call it after the containment level has come out, and if this applies to some variables that are no longer in you, you may be lucky, but this is not to risk it. If, however, the nested function does not apply to anything that is beyond the scope, you should be safe.

This is not more serious than some other problematic parts of the C standard, so I would say that the reasons are mostly historical (C99 is actually no different from K & RC).

There are cases when nested functions with a lexical domain can be useful (consider a recursive inner function that does not need additional stack space for variables in the outer region without the need for a static variable), but I hope you can trust the compiler to correctly embed such functions, then there is a solution with a separate function will be just more detailed.

+5
Aug 28 '09 at 17:41
source share

Nested functions are a very delicate thing. Will you make them close? If not, then they have no advantage for regular functions, since they cannot access local variables. If so, what do you do with the variables allocated by the stack? You must put them elsewhere so that if you later call the nested function, the variable still exists. This means that they will take memory, so you need to allocate space for them on the heap. Without a GC, this means that the programmer is now responsible for clearing the functions. Etc ... C # does this, but they have a GC, and it is a significantly newer language than C.

+5
Aug 28 '09 at 17:48
source share

It would also not be too difficult to add member functions to structures, but they also do not conform to the standard.

Features are not added to the soley-based C standard, regardless of whether they are easy to implement. This is a combination of many other factors, including the point in time at which the standard was written, and what was ordinary and practical.

+3
Aug 28 '09 at 16:48
source share

ANSI C has been around for 20 years. Perhaps in the period from 1983 to 1989, the committee may have discussed this in the light of the state of compiler technology at the time, but if they made their argument lost in a dim and distant past.

+2
Aug 28 '09 at 16:32
source share

I do not agree with Dave Vandervis.

Defining a nested function is a much better coding style than defining it in the global scope, which makes it static and adds the comment: "This is a helper function used only by myfunc ()."

What if you need a helper function for this helper function? Would you add the comment "Is this a helper function for the first helper function used only by myfunc"? Where do you get the names that are needed for all these functions without completely polluting the namespace?

How can convoluted code be written?

But, of course, there is a problem with how to deal with closure, that is, return a pointer to a function that has access to the variables defined in the function from which it returns.

+1
Jan 20 '13 at 16:53
source share

Another reason: it's not entirely clear that nested functions are valuable. More than twenty years ago, I used large-scale programming and maintenance with (VAX) Pascal. We had a lot of old code that heavily used nested functions. At first I thought it was great (compared to the K & RC that I worked with before) and started doing it myself. After some time, I decided that it was a disaster, and stopped.

The problem was that the function could have a large number of variables in the area, counting the variables of all the functions in which it was nested. (There were ten nesting levels in some old code, five were fairly common, and until I changed my mind, I myself coded some of the latter). Variables in the nesting stack can have the same name, so that "internal" functions local variables can mask variables with the same name in more "external" functions. A local variable of a function that is completely closed to it in C-like languages ​​can be changed by calling a nested function. The set of possible combinations of this jazz was almost endless, and a nightmare to understand when you read the code.

So, I started calling this programming construct “semi-global variables” instead of “nested functions” and telling other people working on the code that the only thing worse than a global variable was a semi-global variable, and please don't create more. I would forbid it from language, if I could. Unfortunately, there was no such compiler ...

+1
Aug 12 '13 at 21:12
source share

Either you do not allow referring to local variables of the contained function in the containing one, and nesting is just a function of determining the scope without special use, or you do it. If you do this, this is not such a simple function: you should be able to call a nested function from another when accessing the correct data, and also take into account recursive calls. This is not possible: the methods are well known and well mastered in the development of C (Algol 60 already had a function). But this complicates the organization of the run time and the compiler and prevents simple matching in assembly language (a pointer to a function should contain information about this, as well as there are alternatives such as using one gcc). It was not available for the C language system implementation.

0
Aug 28 '09 at 17:45
source share

Your question and this answer form a tautology ... Why? Because!

I might as well ask why C doesn’t, oh, I don’t know, pass by reference instead of passing by default. Or something else that he does not have.

If you want nested functions, good on ya! Find and use a language that supports them.

-3
Aug 28 '09 at 17:49
source share



All Articles