What does typedef A (*AF)() mean?
Asked Answered
P

3

14

My primary programming language, , was recently open-sourced. In order to improve it, I'm studying the source, which is written in C.

But it's been a long (!) time since I've read or written C, and I wasn't even good at it then. And the way this particular codebase is written is ... idiosyncratic (many APL interpreters, J among them, have their source written in high-level "APL style", even when written in a low-level language; very terse, redundancy eschewed, heavy macro use, etc.)

At the moment, I'm trying to understand the fundamental data structures it employs. The most fundamental one is the typedef A ("A" is for "array"):

typedef struct {I k,flag,m,t,c,n,r,s[1];}* A;

which I understand fine. But I'm struggling to wrap my head around what AF is, two lines later:

typedef A (*AF)();

What does this syntax mean? In particular, what does it mean when things are later declared as "type AF"? Is an AF simply a pointer to an A?

My immediate goal is to interpret memory dumps which include things of type V (for "verb"), whose first two members are AFs:

typedef struct {AF f1,f2;A f,g,h;I flag,mr,lr,rr,fdep;C id;} V;

but my overall goal is larger than that, so please elaborate on the syntax employed in the definition of AF.

Posy answered 11/8, 2015 at 17:36 Comment(12)
AF is a pointer to a function that takes no parameters and returns A.Valine
@dasblinkenlight: That's true in C++. In C, it's a typedef for a function with an unspecified but fixed number and type(s) of parameters and returns A. Very likely it should be defined as typedef A (*AF)(void);. If it's really meant to take an arbitrary number of arguments, then you can very easily have undefined behavior by calling a function incorrectly, with no diagnostic from the compiler.Seemaseeming
This code base is horrible. You should run screaming.Enginery
@KeithThompson Worth pointing out that in J, functions can accept either one argument (both of type A) or two arguments (of type A) and always return an A. There's no such thing as function with zero or more than two arguments, or a function which takes arguments of anything except type A. So what's weird to me is that you say AF can take a fixed number of arguments: seems to me that it should be able to take one or two.Posy
There's no way in C to specify that a function can take one or two arguments. Most functions take a fixed number of arguments, determined when the function is declared/defined; that number can be anywhere from 0 to whatever absurdly large number the compiler supports. A function declared with () takes a fixed but unspecified number of arguments. The corresponding definition determines the actual number and type(s) of the parameters. This is an obsolescent feature. A variadic function, like printf, is declared/defined with , ..., and takes N fixed arguments plus 0 or more ...Seemaseeming
... additional arguments. In C++, you could overload a function so there are two versions, A func(A) and A func(A, A); these would be two distinct functions that happen to have the same name. C doesn't have overloading, but you could define A func1(A), and A func2(A, A). (I don't know J, so I can't comment on how it works.)Seemaseeming
It means you're using the wrong language!Bergquist
The succinctness of J apparently worked its way into the implementation, with terrible results.Featherstitch
For an example where "fixing" what some people call "horrible" would result in something far worse consider FARPROC which is a pointer to a function in a dynamically linked library (where the number and types of args is specified as the left argument to cd ).Ethelinda
@Ethelinda I'm pretty much ignorant of C: can you elaborate on why "fixing" FARPROC would make the situation worse, and why some people might consider FARPROC to be "horrible" in the first place?Posy
Some people claim the "unspecified number of arguments" aspect of the typedef is an obsolete feature of C, so that's one source of "horrible". Meanwhile, "fixing" it would probably mean eliminating the ability to call arbitrary dynamically linked functions. (Or it would mean replacing it with something far more verbose which would probably smash L1 cache).Ethelinda
For the comment of "horrible": Here is a Q&A from the author: Q How do conventional C Programmers react to this? A: With Horror! ---Roger Hui presentation to the British APL Association on 12 Feb 1993.Tharp
P
13

As already answered, an AF (Array Function) is a pointer to a function that returns an A (Array object pointer).

In the definition of V (Verb, ie. function object), there are two AFs. v1 is a pointer to the monadic function implementation, and v2 is the pointer to the dyadic function. If the V represents an operator (adverb), then v1 and v2 are still the monadic and dyadic implementations respectively, but also f g and h may be used to hold (curried) left and/or right arguments. mr lr and rr are monadic-rank, left-rank, and right-rank respectively. And id holds an opcode so a printable representation can still be recovered from the structure.

If any of the operands in f g or h are themselves verbs, their V struct will be at f->k bytes past *f, respectively for g and h, like all "payload data".

A very useful link I found for understanding the basic types in the J implementation is Roger Hui BAA talk notes (2.69M scanned pdf). And the full write-up is at Implementation of J (html).

You might also find my primitive clone instructive. See also my questions here and here.

Postulant answered 11/8, 2015 at 18:12 Comment(2)
Awesome, very specific to my needs (I was wondering about f, g, h). Thanks. I'll take a look at the BAA notes and your clone. Appreciate the help.Posy
I accepted your answer, though it was later than others, because it contains the most detail specific to my project (worth mentioning that I did upvote all the posted answers).Posy
O
13

AF is a typedef for a function pointer. Specifically, AF refers to a pointer to a function that takes an unspecified number of parameters and return a result of type A.

Oxonian answered 11/8, 2015 at 17:38 Comment(6)
Ah, of course. That makes sense in the context of Vs, too, which are functions which process As (and return As). Thanks. I'll accept this when the system lets me.Posy
This is a pointer to a function with 0 arguments. Pointers to functions with variable numbers of arguments use ... syntax.Tjader
@Tjader No, a function with 0 arguments has (void) as parameters list; that would be typedef A (*AF)(void). The answer is correct: it's unspecified number of parameters.Omen
@rlbond: Functions declared with () are very different from variadic functions declared with , .... The former means you still must pass arguments matching the definition, but the compiler won't detect errors (it's an obsolescent feature). The latter means the function can legitimately take a varying number and type(s) of arguments; printf is the most common example.Seemaseeming
AF is not a "pointer" but a type. Please try to stay accurate.Cookhouse
@Cookhouse Thanks. Changed "is a pointer" to "refers to a pointer"Oxonian
P
13

As already answered, an AF (Array Function) is a pointer to a function that returns an A (Array object pointer).

In the definition of V (Verb, ie. function object), there are two AFs. v1 is a pointer to the monadic function implementation, and v2 is the pointer to the dyadic function. If the V represents an operator (adverb), then v1 and v2 are still the monadic and dyadic implementations respectively, but also f g and h may be used to hold (curried) left and/or right arguments. mr lr and rr are monadic-rank, left-rank, and right-rank respectively. And id holds an opcode so a printable representation can still be recovered from the structure.

If any of the operands in f g or h are themselves verbs, their V struct will be at f->k bytes past *f, respectively for g and h, like all "payload data".

A very useful link I found for understanding the basic types in the J implementation is Roger Hui BAA talk notes (2.69M scanned pdf). And the full write-up is at Implementation of J (html).

You might also find my primitive clone instructive. See also my questions here and here.

Postulant answered 11/8, 2015 at 18:12 Comment(2)
Awesome, very specific to my needs (I was wondering about f, g, h). Thanks. I'll take a look at the BAA notes and your clone. Appreciate the help.Posy
I accepted your answer, though it was later than others, because it contains the most detail specific to my project (worth mentioning that I did upvote all the posted answers).Posy
C
12

Let us ignore what A actually is. You then have

typedef int (*AF)();

AF is a pointer to function (aka function pointer) which takes any number of arguments and returns an int. Clearly, by substituting int with A, the content is essentially the same except the return type; the final result therefore qualifies AF as a pointer to function taking any number of arguments and returning A, an alias for a pointer to an anonymous struct.

There's an interesting site that could help converting complex declarations in human-readable text.

Contemn answered 11/8, 2015 at 17:45 Comment(2)
Nice. Thanks in particular for the link to cdecl.org: I will probably need it for this project.Posy
@DanBron: There's also a cdecl program you can install. For Linux, just install the cdecl package. For other OSs, you can probably build it from source.Seemaseeming

© 2022 - 2024 — McMap. All rights reserved.