3 ms·
Correct me if I'm wrong, but isn't a "function" always a pointer in C? That is, there's no such thing as a "value function" in C, right? Given that, what's the
by lomnakkus 10y ago
Correct me if I'm wrong, but isn't a "function" always a pointer in C? That is, there's no such thing as a "value function" in C, right?
Given that, what's the advantage for "your version" of the idiom?
(This may just be nitpicking.)
- has2k1 10y agoYes. Once declared, function pointers are similar to regular functions. They both point to a value that cannot be changed. That value is a block of code.
- tropo 10y agoNo, but C will automatically take the address. The same goes for arrays. You can explicitly take the address of a function, and this is different from taking the address of a function pointer. Pros: beginner confusion; sometimes bugs. Cons: one less character to type; sometimes able to get more out of a macro
- loeg 10y agoFunctions degrade to pointers when passed as values, but they aren't inherently pointers (and these have distinct types, e.g., for C11 _Generic).
- evincarofautumn 10y agoOne advantage is that you can declare functions with it, which is useful when you have many different operations of the same type. For example, take a toy calculator: typedef double binary_operation(double, double); binary_operation add, subtract, multiply, divide; double add(double a, double b) { return a + b; } /* ... */ struct binary_operator { char const *name; binary_operation *operation; } binary_operators[] = { { "+", add }, { "-", subtract }, { "*", multiply }, { "/", divide }, { NULL, NULL }, }; You can also use the function type in parameter lists, but it’s equivalent to a function pointer type. int atexit(void function(void));
- lomnakkus 10y agoWell, yeah, obviously there's less redundancy, but I'm specifically not seeing the advantage that OP mentioned. (Which is all that I'm questioning.)
- loeg 10y agoHere's an example: typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler); Without the typedef, it's much less clear. Edit: It could instead be written as the non-pointer type: typedef void (sighandler_t)(int); And then used as: sighandler_t *signal(int signum, sighandler_t *handler); And as a function declaration: sighandler_t foo; With the pointer in the typedef, the type can't be used to declare functions.
- DSMan195276 10y agoThis is very similar to the 'array-type', which I've written about before (And could talk about if you're interested). Functions (and arrays) degrade into a pointer to themselves when used in most situations (for functions, I can't think of a real case where it doesn't degrade, besides declarations). But the 'func' in this case is the type of a 'function' ('value function' as you're referring). Interestingly, declaring something of type 'func' is the same as forward declaring a function of that type: typedef int func(void); /* These two lines are equivalent */ func foo; int foo(void); Obviously though, the above is of limited usefulness. It is kinda handy to ensure functions are compatible with a certain typedef, but if it isn't you'll generally see warnings or errors in other locations anyway. The advantage of my technique here is that it doesn't 'hide' the pointer inside of the typedef, which I consider poor form. Consider these two: typedef int type1; typedef int type2(void); typedef int (*type3)(void); type1 *var1; type2 *var2; type3 var3; type3 *var4; All of the above are actually pointers, but from the declaration alone you can't tell that `type3 var3` actually declares a pointer. In fact, `type3 var3` and `type2 * var2` declare the exact same thing (minus the name), but `type2 * var2` makes it clear that `var2` is a pointer and not a value type. I find this to be a fairly nice aide in reading, and if you keep this consistent for all types then you don't ever have to worry about a pointer being hidden, or the usage not matching the declaration (IE. You declare it as `type3 var3` but then do something like `* var3`, which looks incorrect unless you know `type3` is actually a pointer). Moreover, lots of people that are newer to C (and even those that aren't but just aren't clear or didn't fully check what `type3` is) will attempt to use `type3 * var`, a double-pointer to a function, when what they really want is `type3 var`, a pointer to a function. There's no confusion over what it is if you don't hide the pointer in the first place, and there's really no great reason to hide it besides not knowing you can avoid hiding it in the first place. Even when you're not new to C, keeping track of things when people do `typedef struct foo * bar` and then `bar * foo2` can get to be a headache really fast. Edit: Fixed formatting
- fanf2 10y agoThe main case where a function does not decay into a pointer is in a function call :-) BUT since ANSI C you can call a function pointer directly: you no longer have to write (*fptr)(arg). So there is automatic invisible conversion in both directions.
- ScottBurson 10y agoI would say that a "function pointer" isn't really a pointer: you can't dereference it or do arithmetic on it. Really, the things we currently call "functions" should be "function literals", and then what's now a "function pointer" could be just a "function".