function pointers for objects in C - c

typedef struct node{
int term;
struct node *next;
}node;
typedef void(*PTR )(void *);
typedef void(*PTR1)(void *,int,int);
typedef int(*PTR2)(void *,int);
typedef void(*PTR3)(void *,int);
typedef void(*PTR4)(void *,void *,void *);
typedef struct list{
node *front,*rear;
PTR3 INSERT;
PTR *MANY;
PTR DISPLAY,SORT,READ;
PTR4 MERGE;
}list;
void constructor(list **S)
{
(*S)=calloc(1,sizeof(list));
(*S)->front=(*S)->rear=NULL;
(*S)->INSERT=push_with_value;
(*S)->READ=read;
(*S)->SORT=sort;
(*S)->DISPLAY=display;
(*S)->MERGE=merger;
(*S)->MANY=calloc(2,sizeof(PTR));
(*S)->MANY[1]=read;
}
int main()
{
list *S1,*S2,*S3;
constructor(&S1);
constructor(&S2);
constructor(&S3);
S1->MANY[1](S1);
S1->SORT(S1);
S1->DISPLAY(S1);
return 0;
}
The void * parameter in all such functions gets typecast to list * inside the function.
Is there any way through which I can call S1->READIT; by changing the MANY[1] to another name like READ_IT;?
I intend to create a common header file, so that I can use it for all my programs.
Since I don't know how many function pointers I will need I intend to create a dynamic array of each function pointer type.

typedef struct list{
node *front,*rear;
PTR3 INSERT;
PTR READIT;
PTR DISPLAY,SORT,READ;
PTR4 MERGE;
}list;
...
(*S)->READIT = read;
...
S1->READIT(S1);

Take a look at the Linux kernel implementation of (doubly linked) lists, as defined here (and following/referenced files). They are used all over the place. Most of the manipulation is done in macros to e.g. run an operation on all nodes of the list.
If what you are trying to define is getting too complicated, step back and look for simpler alternatives. Don't generalize beforehand; if the generalization isn't used it is a waste; if something (slightly) different is later needed, it is a poor match that requires workarounds or even reimplementation.
Take a look at the interfaces exposed by the C++ STL list, those folks have thought long and hard on the matter (in a different setting, though).
Or just bite the bullet and use C++ if you want full-fledged OOP.

Related

Usage of Typedef Struct in C programming

I have a C template which is given me as homework. But before doing homework, I need to understand the usage of "typedef" and "struct" clearly to move on coding. Here is the code;
typedef struct NODE_s *NODE;
typedef struct NODE_s
{
NODE right;
NODE left;
unsigned long data;
int height;
} NODE_t[1];
typedef struct TREE_s *TREE;
typedef struct TREE_s
{
NODE root;
} TREE_t[1];
TREE tree_init();
NODE node_init(unsigned long data);
First of all, what is the line typedef struct NODE_s *NODE; is doing here? Why it is named like a pointer with a *?
Then, after the struct definition, what is the purpose of creating a variable named NODE_t[1], is the square brackets with the number "1" something connected with an array, or it is just something else?
Lastly, when the tree_init(); and node_init(unsigned long data); functions are declared, why the TREE and NODE datatype names are used to the contrary they were declared as *TREE and *NODE before the struct definitions? Thank you for the answers.
The template you were given is this, where I've added numbers to some of the lines for ease of reference:
typedef struct NODE_s *NODE; // 1
typedef struct NODE_s // 2
{
NODE right; // 3
NODE left;
unsigned long data;
int height;
} NODE_t[1]; // 4
typedef struct TREE_s *TREE;
typedef struct TREE_s
{
NODE root;
} TREE_t[1];
TREE tree_init(); // 5
NODE node_init(unsigned long data);
What are the problems here?
As noted in comments, the SO Q&A Is it a good idea to typedef pointers suggests that it is not a good idea to typedef pointers, with limited exceptions for 'pointers to functions' (not relevant here) and perhaps (but probably not) for opaque types. This line does two things: (1) it says "there is a structure type with the tag NODE_s; (2) the name NODE is a synonym for struct NODE_s *. The structure type is incomplete at the moment; no details are known about its members.
This line starts a new typedef, but also starts the definition of the type struct NODE_s (because of the { that follows on the next line).
The type NODE is already known; it can be used here. It means the same as if you wrote struct NODE_s *right;.
The name NODE_t is an alias for the type struct NODE_s[1], an array of 1 struct NODE_s. It isn't clear what this is going to be used for. I have reservations (at best) about its existence. (You can also apply the discussion in points 1, 2, 4 to the struct TREE_s type, mutatis mutandis.)
This is a function declaration, but it is not a prototype declaration. It says that the tree_init() function can be called with any number of arguments of any type because no information is specified about the number or type of those arguments. We do know it is not a variadic function (variable argument list, like printf()) because those must have a full prototype declaration ending with , ...) in scope before they're used. If you want to specify that the function takes no arguments, say so: TREE tree_init(void);.
I think the intent behind the NODE_t and TREE_t types is to allow you to write, for example:
int main(void)
{
TREE_t x = { 0 };
if (x->root != 0)
return 1;
return 0;
}
I'm not convinced whether that's sufficiently helpful to warrant the type compared with using struct NODE_s x and using x.root in the test. It does save you from having to add an & when passing a pointer to a function; again, I'm not sure it is really sufficiently helpful to warrant its existence.
What I would prefer to see as the template is:
typedef struct NODE_s NODE;
struct NODE_s
{
NODE *right;
NODE *left;
unsigned long data;
int height;
};
typedef struct TREE_s TREE;
struct TREE_s
{
NODE *root;
};
extern TREE *tree_init(void);
extern NODE *node_init(unsigned long data);
This removes the pointers from the typedef statements, avoids the somewhat peculiar array types, and uses an explicit prototype for tree_init(). I personally prefer to have function declarations marked with extern; in a header, they'll match the extern on those rare global variables that are declared in the header. Many people prefer not to use extern because the compiler assumes that anyway — so be it; the most important thing is consistency.
The code in main() would now be written:
int main(void)
{
TREE x = { 0 };
if (x.root != 0)
return 1;
return 0;
}
The difference? An arrow -> changed to a dot .. Not a lot of problem there. However, when calling functions, you'd probably use &x whereas with the TREE_t type, you would just write x (because it's an array).

Prevent value from changing on c

I decided to make static library realising doubly linked lists with functions. Its header file is like this now:
#ifndef LISTS
#define LISTS
#define LIST {0, NULL, NULL}
typedef struct node node;
typedef struct list {
unsigned int length;
node *beginning;
node *end;
} list;
void listAppend(list *list, int value);
int listPop(list *list);
char listRemove(list *list, int value);
void listPrint(list *list);
void listClear(list *list);
#endif
i.e. user should initialize list with list myList = LIST;.
Can I prevent list.length from casual changing by user in his code like list.length++?
Usually, if you want to hide implementation from client in pure C, you might use pointers to incomplete types. To do this, you put forward declaration of your struct in .h file and its full declaration in *.c file. You can't even add literal zero to a pointer to incomplete type, not to mention dereference it and/or alter some data.
Also, if you want to go against all odds and put your lists's header on stack, you might want to write a macro around alloca(), however I'm not sure how to calculate size of your struct in *.h file without having its declaration in scope. it's possible via extern const, but IMHO it's too complicated.

Storing and using type information in C

I'm coming from Java and I'm trying to implement a doubly linked list in C as an exercise. I wanted to do something like the Java generics where I would pass a pointer type to the list initialization and this pointer type would be use to cast the list void pointer but I'm not sure if this is possible?
What I'm looking for is something that can be stored in a list struct and used to cast *data to the correct type from a node. I was thinking of using a double pointer but then I'd need to declare that as a void pointer and I'd have the same problem.
typedef struct node {
void *data;
struct node *next;
struct node *previous;
} node;
typedef struct list {
node *head;
node *tail;
//??? is there any way to store the data type of *data?
} list;
Typically, the use of specific functions like the following are used.
void List_Put_int(list *L, int *i);
void List_Put_double(list *L, double *d);
int * List_Get_int(list *L);
double *List_Get_double(list *L);
A not so easy for learner approach uses _Generic. C11 offers _Generic which allows for code, at compile time, to be steered as desired based on type.
The below offers basic code to save/fetch to 3 types of pointers. The macros would need expansion for each new types. _Generic does not allow 2 types listed that may be the same like unsigned * and size_t *. So there are are limitations.
The type_id(X) macros creates an enumeration for the 3 types which may be use to check for run-time problems as with LIST_POP(L, &d); below.
typedef struct node {
void *data;
int type;
} node;
typedef struct list {
node *head;
node *tail;
} list;
node node_var;
void List_Push(list *l, void *p, int type) {
// tbd code - simplistic use of global for illustration only
node_var.data = p;
node_var.type = type;
}
void *List_Pop(list *l, int type) {
// tbd code
assert(node_var.type == type);
return node_var.data;
}
#define cast(X,ptr) _Generic((X), \
double *: (double *) (ptr), \
unsigned *: (unsigned *) (ptr), \
int *: (int *) (ptr) \
)
#define type_id(X) _Generic((X), \
double *: 1, \
unsigned *: 2, \
int *: 3 \
)
#define LIST_PUSH(L, data) { List_Push((L),(data), type_id(data)); }
#define LIST_POP(L, dataptr) (*(dataptr)=cast(*dataptr, List_Pop((L), type_id(*dataptr))) )
Usage example and output
int main() {
list *L = 0; // tbd initialization
int i = 42;
printf("%p %d\n", (void*) &i, i);
LIST_PUSH(L, &i);
int *j;
LIST_POP(L, &j);
printf("%p %d\n", (void*) j, *j);
double *d;
LIST_POP(L, &d);
}
42
42
assertion error
There is no way to do what you want in C. There is no way to store a type in a variable and C doesn't have a template system like C++ that would allow you to fake it in the preprocessor.
You could define your own template-like macros that could quickly define your node and list structs for whatever type you need, but I think that sort of hackery is generally frowned upon unless you really need a whole bunch of linked lists that only differ in the type they store.
C doesn't have any runtime type information and doesn't have a type "Type". Types are meaningless once the code was compiled. So, there's no solution to what you ask provided by the language.
One common reason you would want to have a type available at runtime is that you have some code that might see different instances of your container and must do different things for different types stored in the container. You can easily solve such a situation using an enum, e.g.
enum ElementType
{
ET_INT; // int
ET_DOUBLE; // double
ET_CAR; // struct Car
// ...
};
and enumerate any type here that should ever go into your container. Another reason is if your container should take ownership of the objects stored in it and therefore must know how to destroy them (and sometimes how to clone them). For such cases, I recommend the use of function pointers:
typedef void (*ElementDeleter)(void *element);
typedef void *(*ElementCloner)(const void *element);
Then extend your struct to contain these:
typedef struct list {
node *head;
node *tail;
ElementDeleter deleter;
ElementCloner cloner;
} list;
Make sure they are set to a function that actually deletes resp. clones an element of the type to be stored in your container and then use them where needed, e.g. in a remove function, you could do something like
myList->deleter(myNode->data);
// delete the contained element without knowing its type
create enum type, that will store data type and alloc memory according to this enum. This could be done in switch/case construction.
Unlike Java or C++, C does not provide any type safety. To answer your question succinctly, by rearranging your node type this way:
struct node {
node* prev; /* put these at front */
node* next;
/* no data here */
};
You could then separately declare nodes carrying any data
struct data_node {.
data_node *prev; // keep these two data members at the front
data_node *next; // and in the same order as in struct list.
// you can add more data members here.
};
/* OR... */
enter code here
struct data_node2 {
node node_data; /* WANING: this may look a bit safer, but is _only_ if placed at the front.
/* more data ... */
};
You can then create a library that operates on data-less lists of nodes.
void list_add(list* l, node* n);
void list_remove(list* l, node* n);
/* etc... */
And by casting, use this 'generic lists' api to do operation on your list
You can have some sort of type information in your list declaration, for what it's worth, since C does not provide meaningful type protection.
struct data_list
{
data_node* head; /* this makes intent clear. */
data_node* tail;
};
struct data2_list
{
data_node2* head;
data_node2* tail;
};
/* ... */
data_node* my_data_node = malloc(sizeof(data_node));
data_node2* my_data_node2 = malloc(sizeof(data_node2));
/* ... */
list_add((list*)&my_list, (node*)my_data_node);
list_add((list*)&my_list2, &(my_data_node2->node_data));
/* warning above is because one could write this */
list_add((list*)&my_list2, (node*)my_data_node2);
/* etc... */
These two techniques generate the same object code, so which one you choose is up to you, really.
As an aside, avoid the typedef struct notation if your compiler allows, most compilers do, these days. It increases readability in the long run, IMHO. You can be certain some won't and some will agree with me on this subject though.

typedef vs. no typedef with structs and enums in C

In C, is there any effective difference between declaring a struct as
typedef struct {...} Foo;
and
struct Foo {...};
I know the second requires you to prefix uses with struct, but what are the differences between these two definitions that I'll notice when writing or executing the program? What about with enums?
Update: please see comments attached to answer for clarification.
Original post.
Besides having to write "struct" everywhere, something else of note is that using a typedef will allow you to avoid subtle syntax errors when working with pointers:
Quote:
Typedefs can also simplify declarations for pointer types. Consider
this:
struct Node {
int data;
struct Node *nextptr;
};
Using typedef, the above code can be rewritten like this:
typedef struct Node Node;
struct Node {
int data;
Node *nextptr;
};
In C, one can declare multiple variables of the same type in a single
statement, even mixing pointer and non-pointers. However, one would
need to prefix an asterisk to each variable to designate it as a
pointer. In the following, a programmer might assume that errptr was
indeed a Node *, but a typographical error means that errptr is a
Node. This can lead to subtle syntax errors.
struct Node *startptr, *endptr, *curptr, *prevptr, errptr, *refptr;
By defining a Node * typedef, it is assured that all the variables
will be pointer types.
typedef struct Node *NodePtr;
...
NodePtr startptr, endptr, curptr, prevptr, errptr, refptr;
If you write
typedef struct {...} foo;
It saves you from having to write struct foo everywhere: you can just write foo.
(You get this notational convenience for free in C++ by the way).
I would look at this SO question and then summarize that there is no appreciable functional difference between struct { ... } and typedef struct { ... } although the latter may make your code less cumbersome and easier to understand if used correctly.

Any way in C to forward declare struct in header without having to use pointer in other files?

Suppose I have this in list.h:
typedef struct list_t list_t;
typedef struct list_iter_t list_iter_t;
list_iter_t iterator(list_t *list);
and then define them in list.c:
typedef struct node_t {
...
} node_t;
struct list_iter_t {
node_t *current;
// this contains info on whether the iterator has reached the end, etc.
char danger;
};
struct list_t {
...
}
list_iter_t iterator(list_t *list) {
list_iter_t iter;
...
return iter;
}
Is there anything I can do aside from including the struct declaration in the header file so that in some file test.c I can have:
#include "list.h"
void foo(list_t *list) {
list_iter_t = iterator(list);
...
}
Like maybe tell the compiler the storage size of list_iter_t somehow? It's inconvenient to have to use a pointer (not because it's a pointer, but for other reasons), but at the same time I would like to hide the implementation details as much as possible.
The succinct answer is "No".
The way you tell the compiler the size of a struct is by telling it the details of how the struct is structured. If you want to allocate an object, rather than a pointer to the object, the compiler must know the complete type of the object. You also can't access the members of a structure via a pointer to the structure if the type is incomplete. That is, the compiler must know the offset and type of the member to generate the correct code to access someptr->member (as well as to allocate somevalue or access somevalue.member).
It is possible to tell the compiler the size of the structure, using a dummy definition like:
struct node_t {
char dummy[sizeof(struct { ... })];
};
(with the proper definition instead available to the implementation file).
Formally this causes undefined behaviour; it is likely to somewhat work in practice, though.
You are probably best off just including the proper structure definition though, and leaving a comment to the effect that code should simply not touch the internal members.

Resources