7
$\begingroup$

An anonymous function behaves the same as a regular function with no identifier attached. One could be passed as a callback or stored in a function pointer variable. In C++ they can be written as follows:

int (*add)(int, int) = [](int x, int y) -> int {return x+y;};

However in pure C there is no compound-literal style syntax to create anonymous functions:

int (*add)(int, int) = (int(int x, int y)){return x+y;};

One must clutter the global namespace to use bsearch(), qsort(), or construct an array of many functions.

I realize C is older than C++ and did not always have compound literals (anonymous variables) in the first place. However those were added in C99 but anonymous functions were not. Not even in C23.

Are there technical limitations or other disadvantages that I do not know of that prevents identifier-less functions?

$\endgroup$
2
  • 4
    $\begingroup$ C is over 50 years old and needed to run in reasonable time on that hardware. A lot of the answers to why it is the way it is were to make the compiler more efficient. $\endgroup$
    – Bbrk24
    Commented May 17, 2023 at 0:54
  • $\begingroup$ @user16217248 eh, usually you can flag it instead, and you should. Just feel free to flag any comment when they are not needed anymore. $\endgroup$ Commented May 18, 2023 at 6:30

2 Answers 2

7
$\begingroup$

Closures are complicated

C is and always has been a simple language, and it tries to remain that way even today. If you wanted to add the ability to make simple non-closing functions as local variables, that's easy and wouldn't affect the semantics of the language in the slightest. A non-closing function would simply compile to a top-level static function with a generated name and would only be accessible inside of the scope it was defined in.

However, generally when people want anonymous functions, what they really want is closures. Closures can use local variables in the surrounding scope, in addition to the data globally available in the current file. That's what allows tricks like

def add_to_each(lst, number):
    return map(lambda x: x + number, lst)

to work. The lambda here closes around the variable number. It's no longer just an ordinary function in the machine sense of the word; now it's a function plus some extra state.

In C++, if you create a lambda that doesn't close around any variables, it's guaranteed to be available as a function pointer, i.e. a plain old ordinary C++98-style function. But if you need a nontrivial closure, then C++ does magic to make a strange object that just works the way you expect. That object's type is no longer int(*)(int, int). Its type is in fact special-made just for this situation, and you can't refer to it by name (though it is convertible to std::function<int(int, int)>, which is another piece of C++ magic). All of this is fine in C++, which is "C plus insane high-level shenanigans". But C is designed to be simple and predictable, so the language avoids adding all of this code generation for the same reason templates were never added to C: it would just add so much complexity.

$\endgroup$
1
  • $\begingroup$ In C++, even non-capturing lambda's have a unique type. They're only convertible to function pointers, but every lambda type is a class type. $\endgroup$
    – MSalters
    Commented Dec 4, 2023 at 11:34
3
$\begingroup$

Apple did it, so the answer is obviously No, there is no technical limitation.

Apple added a non-standard feature called Blocks to their implementation of C in order to support easy use of the Grand Central Dispatch concurrency mechanism. Unlike GCC's non-standard nested functions, which cannot be called after the outer function ends, Apple's Blocks are proper closures which can close over their surrounding environment and can outlive their outer function.

$\endgroup$
1
  • $\begingroup$ Looking at the implementation details, it's basically std::function as a compiler built-in. Block objects have constructors and destructors that are invoked automatically by the compiler and allocate heap space, etc. Of course it's possible (how could it not be?) but it's rather un-C-like, I'd say. $\endgroup$
    – benrg
    Commented Dec 24, 2023 at 2:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .