2

I'm studying in-depths of languages, so I can understand what's happening in code, rather than print some things and watch and see what happens.

Recently, in search for better implementation for class function table I found myself stumbled upon this C language standard: http://www.iso-9899.info/wiki/Typedef_Function_Type

I've tried it out and it seems working feature:

typedef void fnr(int x);

main()
{
    fnr t;
}

This seemed a glorious day for me searching the way to pack up functions into my structure, until I realized, that fnr t; is not as useful as I had intended. It can neither be assigned, nor used the proper way I wished it to be (probably lambda for C-users). It does not even exist in disassembly!

What does this language feature do? What can it be used for besides simplifying function pointers?

dbush
  • 205,898
  • 23
  • 218
  • 273
  • It can be assigned if declared as `fnr *t;`, or without needing the `*` at variable declaration time, just change the `typedef` to `typedef void (*fnr)(int);` so you can use `fnr t;` and assign it normally. That said, I'm extremely unclear on your goal here. `typedef` just allows you to alias complicated things to simple names, you seem to want it to do something very different. – ShadowRanger Mar 19 '19 at 18:47
  • *"good use(not just creating pointers)"* Using function typedefs for making pointer-to-function types *readable* is one of the most important uses of them, imho. *"`fnr t;` is a useless string"* `fnr t;` expands to `void t(int x);`. Do you know what function declarations are and what they're used for? Whether it's a good idea to use typedefs to declare functions is a different question. – HolyBlackCat Mar 19 '19 at 18:47
  • @HolyBlackCat this is not a function declaration, this is type definition. If you declare the function with the same name it won't work – Ilya Pakhmutov Mar 19 '19 at 19:03
  • 1
    @IlyaPakhmutov It's a function declaration, [see for yourself](http://coliru.stacked-crooked.com/a/da866b146ec2150f). – HolyBlackCat Mar 19 '19 at 19:06
  • @HolyBlackCat It might be more obvious if you declare it before `main` and define after. – Eugene Sh. Mar 19 '19 at 19:07
  • @HolyBlackCat i seemed you just used function, but not fnr t; – Ilya Pakhmutov Mar 19 '19 at 19:08
  • You're right, it wasn't a good example. Check out this: http://coliru.stacked-crooked.com/a/140a93812bbe6ad6 – HolyBlackCat Mar 19 '19 at 19:09
  • 1
    @IlyaPakhmutov In that example the line `fnr t;` is exactly the same as `void t(int x);` which is a function declaration. – Eugene Sh. Mar 19 '19 at 19:09
  • @EugeneSh. This sounds convincing, yet still half useless, but thanks for clarifying :) – Ilya Pakhmutov Mar 19 '19 at 19:14
  • Well.. half useless = half useful :) – Eugene Sh. Mar 19 '19 at 19:15

2 Answers2

8

You've declared fnr as a function type. While a function type cannot be assigned to, a pointer to a function type can. For example:

typedef void fnr(int x);

void f(int x)
{
    printf("x=%d\n", x);
}

int main()
{
    fnr *t = f;
    t(1);
}

You could also define the typedef as a function pointer:

typedef void (*fnr)(int x);
...
fnr t = f;

Using a typedef for a function pointer is most useful when a function pointer is either passed to or returned from a function. As an example, let's look at the signal function which does both:

  typedef void (*sighandler_t)(int);

  sighandler_t signal(int signum, sighandler_t handler);

The second parameter to this function is a pointer to a signal handling function, and it also returns a pointer to a signal handling function. Without the typedef, it would look like this:

void (*signal(int signum, void (*handler)(int)))(int)
dbush
  • 205,898
  • 23
  • 218
  • 273
  • Ok, that doesn't seem obvious, that I know, what fPointers are, but the question was: Was this typedef of a function is for? I know i can create pointers out of it, but C does not even have a bool in its standard, but this, obviously useless typedef is presented. But most of all, I cannot assign anything to it. The only thing it does is clarify the func pointer pass to callback functions. – Ilya Pakhmutov Mar 19 '19 at 19:00
  • 2
    @IlyaPakhmutov *"C does not even have a bool in its standard"* C has booleans since C11. *"this, obviously useless typedef is presented"* It has some uses, as the answer shows. It doesn't seem wise to me to specifically forbid typedefing function types (while allowing all other types) just because they allegedly don't have many uses. – HolyBlackCat Mar 19 '19 at 19:15
  • 1
    @IlyaPakhmutov C has a Boolean type, btw... `_Bool`. Also see the `` header. – Shawn Mar 19 '19 at 19:16
  • @Shawn I... did't even know that... why so complex why not just `bool` (rhetorical question). I guess I'm old – Ilya Pakhmutov Mar 19 '19 at 19:19
  • 3
    @IlyaPakhmutov it was only added 20 years ago, but sadly much C educational material has yet to catch up to C99, much less newer versions. C uses reserved identifiers for new keywords to avoid breaking existing code (lots of older stuff typedefed or defined `bool`) and provides a header to let you use a more conventional non-reserved name if you want: `_Bool` and `bool`, `_Complex` and `complex`, etc. – Shawn Mar 19 '19 at 19:25
  • 1
    @Shawn at this point I find myself ignorant, because I can hardly read (because of me) and questions to teachers of prog or programmers is the only way for me to get knowledge. That's why I came up to idea of learning in-depths of a C and C++. I want to git gud :) – Ilya Pakhmutov Mar 19 '19 at 19:28
2

The typedef facility acts primarily as an abstraction mechanism - it's used to create an alias for a type name that either hides or simplifies implementation details. The FILE type in stdio.h is probably the canonical example in C - FILE is a typedef name for some other type (often a struct type) that stores state information for a stream. We don't mess with a FILE object's contents directly - instead, we create a pointer to a FILE that's operated on by the various C I/O routines (fopen, fclose, fread, fwrite, fscanf, fprintf, etc.).

EDIT

As for typedef-ing function types...

You'll often see it used to simplify a callback declaration:

typedef void (*callback)( /* callback arguments */ );
...
void do_something( T arg1, T arg2, callback c );

callback is an alias for the type "pointer to function taking some callback arguments and returning void".

John Bode
  • 119,563
  • 19
  • 122
  • 198
  • because the content of a FILE is a placeholder ` typedef struct _iobuf { void* _Placeholder; } FILE;` – Ilya Pakhmutov Mar 19 '19 at 19:24
  • 1
    @IlyaPakhmutov: It's because the thing `FILE` aliases varies *widely* by platform. On my SLES10 system it's `typedef struct _IO_FILE FILE;`, where `_IO_FILE` is `struct _IO_FILE { int _flags; char* _IO_read_ptr; char * _IO_read_end; char* _IO_read_base; ...};`, whereas on MaxOS it's `typedef struct __sFILE { unsigned char *_p; int _r; int _w; short _flags; ... } FILE;`. – John Bode Mar 19 '19 at 19:44