Prevent value from changing on c - 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.

Related

What is causing an Identifier Error in C from Header File?

I am new to C and seem to have a misunderstanding of how header files seem to work.
For simplicities sake, I have three files: tree.h, lib.c, and main.c
In tree.h, I have
struct Node
{
void* item;
Node** nodes;
};
struct Tree
{
Node* tree_root;
int depth, item_size;
};
void initializeTree(Tree*, int);
It is my understanding that this initializeTree method is a function "signature', and that the compiler then will know a little about the function whenever I call it in lib.c, or any other .c file that includes the header file tree.h.
However, in lib.c I have the error 'identifier Tree is undefined'.
#include <tree.h>
void initializeTree(Tree* tree, int item_size)
What is causing this error? Would the compiler not be able to 'see' the Tree struct from the included header file?
There is no Tree, there is only a struct Tree(a). While C++ allows the short form, C does not.
In C++, a struct is a slight variation on a class and they are both types accessible without the struct/class prefix. However, the rules in C are different because, despite the similarities and history of the two languages, they are now very different beasts.
So, in C, you either have to use the full type name:
struct Tree { blah blah };
void initializeTree(struct Tree *, int);
or typedef it thus:
typedef struct sTree { blah blah } Tree; // struct sTree =~ Tree
void initializeTree(Tree *, int);
(a) You have the same issue with Node, by the way.

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.

C - Need help implementing an ADT

I'm working on a school assignment and I'm having trouble understanding how to use an ADT. Basically, I need to implement a symbol table ADT that stores <key, value> pairs. The value associated with a key is an arbitrary object defined by the user that is passed to the ADT by a void pointer. I have the header file already included, I just need to make the source file for it.
The declaration I am stuck on is for the structure itself. It is a symbol table object pointerd to by a pointer of type SymTable_T. It should be able to make copies of <key, value> pairs inserted into it and these copies should be destroyed when deleted from the table or when the table itself is destroyed.
The implementation should employ a hash table that uses chaining to resolve collisions. I already am familiar with hashing, so there is no trouble there.
This is what I came up with:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "symTable.h"
#define DEFAULT_TABLE_SIZE 61
#define HASH_MULTIPLIER 65599
typedef struct SymTable *SymTable_T;
{
char *key;
int value;
struct SymTable *next; //linked list
};
Can someone point me in the right direction? Could someone explain to me the essentials of implementing an ADT? Thank you so much in advance!
The essence of an abstract data type is that client code has no insight whatsoever in the structure of values of that type - which also implies that the implementation of any functions dealing with such values is opaque.
In your example, it means that you do not define the struct in the header file but merely use a forward declaration. For traversal, you may also want to define an equally opaque iterator type, e.g.
struct symtable;
struct symtable_iterator;
...and then a collection of functions working with the table, e.g.
/* Create symtable, destroy it, insert values. */
void symtable_alloc(struct symtable **table);
void symtable_free(struct symtable *table);
void symtable_insert(struct symtable *table, const char *key, void *value);
/* Create symtable iterator, destroy it, access key/value. */
void symtable_iterator_alloc(struct symtable *table, struct symtable_iterator **it);
void symtable_iterator_free(struct symtable_iterator *it);
bool symtable_iterator_next(struct symtable_iterator **it);
const char *symtable_iterator_key(struct symtable_iterator *it);
void *symtable_iterator_value(struct symtable_iterator *it);
That's all you should put into the header file. In the implementation (.c) file, you would actually define the structure and its fields - but that code is hidden from clients.
You could use them like
struct symtable *table;
symtable_alloc(&table);
symtable_insert(table, "one", "eins");
symtable_insert(table, "two", "zwei");
symtable_insert(table, "three", "drei");
struct symtable_iterator *it;
symtable_iterator_alloc(table, &it);
while (symtable_iterator_next(&it)) {
printf("%s: %s\n", symtable_iterator_key(it), symtable_iterator_value(it));
}
symtable_iterator_free(it);
symtable_free(table);
Note how the set of functions clearly defines the API of the data structure, but the actual type is abstract - there's no information which gives away the implementation of the table, e.g. whether it's a linked list or a hash table or something else.

function pointers for objects in 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.

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