How can I declare multiple function pointer types in one typedef declaration?
Multiple declaration in C/C++ is misleading as *
is linked to variable and not to the type:
typedef int a, *b, (*c)();
static_assert(std::is_same_v<int, a>);
static_assert(std::is_same_v<int*, b>);
static_assert(std::is_same_v<int (*)(), c>);
So your one-liner would be
typedef void(*the_name_1)(...), (*the_name_2)(...);
Declaration of typedef with pointer
From the semantics of typedef
, chapter §6.7.8, C11
document,
In a declaration whose storage-class specifier is
typedef
, each declarator defines an
identifier to be a typedef name that denotes the type specified for the identifier [...]
So, basically, typedef
is used to create an alias for a given type.
Also, to expand on that,
A
typedef
declaration does not introduce a new type, only a
synonym for the type so specified. That is, in the following declarations:
typedef T type_ident;
type_ident D;
type_ident
is defined as atypedef
name with the type specified by the declaration
specifiers inT
(known asT
), and the identifier inD
has the type ‘‘derived-declaratortype-
list T ’’.
In your code, you are trying to typedef
two different types (i.e, struct image *
and an unnamed struct
) to a same alias name, which is the cause of the issue.
Solution: You don't need to typedef
the structure declaration in your .c
file, use a simple declaration, like
struct image {
char nbrMagique[10];
unsigned long imgLarg;
unsigned long imgHaut;
unsigned long imgSeuilMax;
unsigned long **imageMatrice;
} ;
That said, in general, typedef
-ing pointers is considered a confusing coding style, which reduces readability, IMHO, avoid typedef-ing pointers.
Regarding the part
But what does the pointer
*
in the signature of thetypedef
mean?
It means, the new alias is pointer type. For the case,
typedef struct image * Image;
both
Image iPointer = NULL;
and
struct image * againIPointer = NULL;
are same.
In C, is it good form to use typedef for a pointer?
I would use pointer typedefs only in situations when the pointer nature of the resultant type is of no significance. For example, pointer typedef is justified when one wants to declare an opaque "handle" type which just happens to be implemented as a pointer, but is not supposed to be usable as a pointer by the user.
typedef struct HashTableImpl *HashTable;
/* 'struct HashTableImpl' is (or is supposed to be) an opaque type */
In the above example, HashTable
is a "handle" for a hash table. The user will receive that handle initially from, say, CreateHashTable
function and pass it to, say, HashInsert
function and such. The user is not supposed to care (or even know) that HashTable
is a pointer.
But in cases when the user is supposed to understand that the type is actually a pointer and is usable as a pointer, pointer typedefs are significantly obfuscating the code. I would avoid them. Declaring pointers explicitly makes code more readable.
It is interesting to note that C standard library avoids such pointer typedefs. For example, FILE
is obviously intended to be used as an opaque type, which means that the library could have defined it as typedef FILE <some pointer type>
instead of making us to use FILE *
all the time. But for some reason they decided not to.
typedef with pointer in C
Short version:
typedef ListNode *ListNodePtr;
defines ListeNodePtr
as a pointer to ListNode.
You may wonder why the asterisk is "sticking" to ListNodePtr
here. That's because in C declarations, being a pointer is considered a type modifier, so in a declaration, it's part of the declarator (the identifier of the variable or typedef
'd type).(*) This is relevant as soon as you have multiple declarations in a single line, e.g. the following:
int *a, b;
would define a pointer to int a
and a plain int b
.
You could write it as
int* a, b;
but that would be very confusing, because b
would still not be a pointer.
All that being said, I personally consider it bad style to typedef
a pointer, because as a C programmer, you know the meaning of an asterisk. Hiding it behind a typedef
(and as done here, replacing it by some non-standard suffix like "Ptr") just makes the code harder to read for others.
(*) added footnote here: the reasoning behind this design is that declarations should look the same as usage. *a
dereferences a pointer, so *a
should as well declare a pointer.
Is it a good idea to typedef pointers?
This can be appropriate when the pointer itself can be regarded as a "black box", that is, a piece of data whose internal representation should be irrelevant to the code.
Essentially, if your code will never dereference the pointer, and you just pass it around API functions (sometimes by reference), then not only does the typedef reduce the number of *
s in your code, but also suggests to the programmer that the pointer shouldn't really be meddled with.
This also makes it easier to change the API in the future if the need arises. For instance, if you change to using an ID rather than a pointer (or vice versa) existing code won't break because the pointer was never supposed to be dereferenced in the first place.
Typedef function pointer?
typedef
is a language construct that associates a name to a type.
You use it the same way you would use the original type, for instance
typedef int myinteger;
typedef char *mystring;
typedef void (*myfunc)();
using them like
myinteger i; // is equivalent to int i;
mystring s; // is the same as char *s;
myfunc f; // compile equally as void (*f)();
As you can see, you could just replace the typedefed name with its definition given above.
The difficulty lies in the pointer to functions syntax and readability in C and C++, and the typedef
can improve the readability of such declarations. However, the syntax is appropriate, since functions - unlike other simpler types - may have a return value and parameters, thus the sometimes lengthy and complex declaration of a pointer to function.
The readability may start to be really tricky with pointers to functions arrays, and some other even more indirect flavors.
To answer your three questions
Why is typedef used?
To ease the reading of the code - especially for pointers to functions, or structure names.The syntax looks odd (in the pointer to function declaration)
That syntax is not obvious to read, at least when beginning. Using atypedef
declaration instead eases the readingIs a function pointer created to store the memory address of a function?
Yes, a function pointer stores the address of a function. This has nothing to do with thetypedef
construct which only ease the writing/reading of a program ; the compiler just expands the typedef definition before compiling the actual code.
Example:
typedef int (*t_somefunc)(int,int);
int product(int u, int v) {
return u*v;
}
t_somefunc afunc = &product;
...
int x2 = (*afunc)(123, 456); // call product() to calculate 123*456
How to define function type with typedef?
The alias name should be placed where a variable name would be if it was a variable declaration.
Here:
typedef int (*order) (void *, void *);
// ^~~~~
Or, if you want a function type rather than a pointer-to-function:
typedef int order(void *, void *);
C typedef of pointer to structure
Absolutely valid.
Usually, you can take full advantage of this way by defining two types together:
typedef struct
{
int a;
int b;
} S1, *S1PTR;
Where S1 is a struct and S1PTR is the pointer to this struct.
How to Use Typedef Structure Name with Pointer
A little clarification
typedef struct node {
unint32_t size;
struct node * link;
} *ListNode;
creates a type called ListNode
. It is a pointer to a struct node
. It is not a struct node
So when you do
sizeof(ListNode)
you get the size of a pointer, not the size of struct node
You needed to do
sizeof(struct node)
A very common thing to do is this
typedef struct node {
uint32_ size;
struct node* link;
} *PListNode, ListNode;
this creates 2 types
- PlistNode which is a pointer to a
struct node
- ListNode which is a
struct node
the 'P' is a reminder that this is a pointer
so now you can do
PListNode pn = malloc(sizeof(ListNode));
Related Topics
Why Is the Console Closing After I'Ve Included Cin.Get()
How Does Calling Srand More Than Once Affect the Quality of Randomness
Troubles with Boost::Spirit::Lex & Whitespace
How to Declare Std::Unique_Ptr and What Is the Use of It
Read Func Interp of a Z3 Array from the Z3 Model
#Include Absolute Path Syntax in C/C++
Skipping Expected Characters Like Scanf() with Cin
How to Change the Precision of Printing with the Stl
Why Does Std::Stack Use Std::Deque by Default
Dereferencing One Past the End Pointer to Array Type
How to Use Other C++ Compilers with Cuda on Windows
When Does an Incomplete Type Error Occur in C++
Auto Keyword Behavior with References
Access to Method Pointer to Protected Method
Multiple Classes in a Header File VS. a Single Header File Per Class