How to Typedef a Type and the Same Type's Pointer

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 a typedef name with the type specified by the declaration
specifiers in T (known as T), and the identifier in D 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 the typedef 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 a typedef declaration instead eases the reading

  • Is 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 the typedef 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



Leave a reply



Submit