adambard / learnxinyminutes-docs

Code documentation written as code! How novel and totally my idea!
https://learnxinyminutes.com/
Other
11.49k stars 3.34k forks source link

[c/en] Could use simpler function `typedef` syntax #2850

Open noncombatant opened 7 years ago

noncombatant commented 7 years ago
typedef void (*my_fnp_type)(char *);

This is legal, and IMHO more understandable:

typedef void my_fnp_type(char* meaningful_name);

As I'll show below, this syntax is unnecessarily hairy as well:

void str_reverse_through_pointer(char *str_in) {
  // Define a function pointer variable, named f.
  void (*f)(char *); // Signature should exactly match the target function.
  f = &str_reverse; // Assign the address for the actual function (determined at run time)
  // f = str_reverse; would work as well - functions decay into pointers, similar to arrays
  (*f)(str_in); // Just calling the function through the pointer
  // f(str_in); // That's an alternative but equally valid syntax for calling it.
}

I.e. the alternative syntax is less nasty. Why bother with the nasty flavor? :)

The only quirk is, when putting such a function type as a member of a struct, you do need to give it a *:

~ $ make test
clang -Wall -Wextra -Werror -O0 -ansi -pedantic -std=c11    test.c   -o test
~ $ ./test 
Hello, whirled!
~ $ cat test.c
#include <stdio.h>

typedef void printer(const char* message);

typedef struct {
  printer* function;
  const char* message;
} Printer;

void print(const char* message) {
  puts(message);
}

int main() {
  Printer p = { .function = print, .message = "Hello, whirled!" };
  p.function(p.message);
}

You don't need the * when passing such function typedefs to other functions. Just for struct members. I find this greatly improves the readability of function types, which is good, since they're so useful. The unnecessary ugliness of the classic style makes me sad. :)

Also I find the named struct member initializers improve readability (and I wish C++ had them).

adambard commented 7 years ago

I believe you, but available evidence suggests that you are nearly the only person in the world who writes function pointer typedefs this way. Do you know which version of the syntax they appeared in?

noncombatant commented 7 years ago

I don't know what version that syntax became legal in; AFAIK, it has always been legal. I can build it without warnings in C 89 mode on both clang and GCC:

$ cat f.c
typedef int goat_func(int goat);

int f(int goat) {
  return goat + 42;
}

int main() {
  goat_func* x = f;
  return x(1);
}
$ CC=gcc make f
gcc -Wall -Wextra -Werror -std=c89 -ansi -pedantic -O0    f.c   -o f
$ rm f && CC=clang make f
clang -Wall -Wextra -Werror -std=c89 -ansi -pedantic -O0    f.c   -o f
$

On Tue, Sep 12, 2017 at 10:29 PM, Adam Bard notifications@github.com wrote:

I believe you, but available evidence suggests that you are nearly the only person in the world who writes function pointer typedefs this way. Do you know which version of the syntax they appeared in?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/adambard/learnxinyminutes-docs/issues/2850#issuecomment-329063179, or mute the thread https://github.com/notifications/unsubscribe-auth/AAWv1cbaBpcQ_QUe1Q4ts0_0hAkcu4e9ks5sh2grgaJpZM4PSeBw .

-- https://noncombatant.org/