C - Linked List and pointer problem - c

Hey,
I'm a beginner in C and tried to implement my own linked list implementation, that basically looks like this:
struct Element
{
void *value;
struct Element *next;
};
typedef struct
{
struct Element *first;
struct Element *last;
unsigned int size;
} LinkedList;
void LinkedList_init(LinkedList *this)
{
this->size = 0;
this->first = NULL;
this->last = NULL;
}
void LinkedList_add(LinkedList *this, void *value)
{
struct Element *node = malloc(sizeof(struct Element));
node->value = value;
node->next = NULL;
if (this->size == 0)
this->first = this->last = node;
else
{
this->last->next = node;
this->last = node;
}
this->size++;
}
So in short, I want a linked list that can hold arbitrary types - I heard, this is possible in C by using void pointers.
The problem now arises, when I want to use that implementation, for example with a structure as value:
typedef struct
{
int baz;
} Foo;
int main(void)
{
LinkedList list;
Foo bar;
bar.baz = 10;
LinkedList_init(&list);
LinkedList_add(&list, (void *) &bar);
/* try to get the element, that was just added ... */
Foo *firstElement = (Foo *)list.first;
/* ... and print its baz value */
printf("%d\n", firstElement->baz);
return 0;
}
The last printf call just prints values like -1077927056, which look like a memory address. So it's probably a problem with pointers. After searching the web the last few days for a similar issue on the web (I had no luck with that), I tried to throw my own logic away and tested various random *& combinations. Turns out, that was a dead end, too. :(
It's probably something simple for a more experienced C programmer, but I just can't find the answer. Please help :D

list.fist is a struct Element.
Try:
Foo *firstElement = (Foo *)(list.first->value);

Related

Simple Struct definition in C for Red Black Tree

I don't use the C language since years and now I need it again.
I'm trying to build a Red-Black Tree but I'm stuck at the beginning because I'm missing something about "structs".
Take a look to my "structs" declarations please, they are easy.
This is a header file included in Red_black_tree.c
#define BLACK 0 //defalut color
#define RED 1 //
struct Node { //create a black node by default, to have a red one look at "create_red_node"
struct Node *left = NULL;
struct Node *right= NULL;
int key = 0;
int value = 0;
char color = BLACK;
};
struct Root_t {
struct Node* Root;
};
struct Node* create_node () {
struct Node* black = (Node*) malloc (sizeof(Node));
return black;
}
struct Node* create_red_node () {
struct Node* red = create_node ();
red->color=RED;
return red;
}
Root_t* create_tree () {
struct Root_t* fake=(Root_t*) malloc (sizeof(Root_t));
struct fake->Root->left=create_red_node ();
struct fake->Root->right=create_red_node ();
return fake;
}
I compiled with "gcc Red_black_tree.c -o RBTree".
GCC says something like : "expected ';' at end of declaration list" 7 times, or "must use 'struct' tag to refer to type... ", "expected identifier...".
What do you think, is it good to create RBTree?
In C, you can not assign while you define the members of a struct
Instead of
struct T {
int a = 1;
int b = 2;
};
you need something like
struct T {
int a;
int b;
};
...
struct T t = {.a = 1, .b = 2};
In addition, all your members are set to 0 (NULL is an alias of (void *)0), when you want to allocate memory and initialize all to zero at the same time you can use calloc
struct Node* black = calloc(1, sizeof(*black)); // Dont cast malloc and friends
And here:
struct fake->Root->left=create_red_node();
, you don't want the struct keyword, instead:
fake->Root->left=create_red_node();
Another suggestion: do not hardcode the data of the red-black-tree in the structure, (int key, value;) even if it works you end up with a non reusable container, instead, use a generic pointer to void (void *data;) and a callback to your comparison functions in the implementation.
struct Node *insert(struct Node *root, int (*comparer)(const void *, const void *)) ...

Adding elements to linked list inside a linked list in C

I'm trying to create a small list for each element in a main list. I have the main list working fine but I don't know how to access and add elements to the small list.
struct smallList
{
char data;
struct smallList *next;
};
struct bigList
{
char data;
struct bigList *next;
struct smallList *head;
} *root;
When I add stuff to the main list, I declare for each new node:
newNode->head = NULL;
I use this function to get the current pointer to an element in main list:
struct bigList *pointer = getPointer(root, value);
Then, to add stuff to its smallList| using that pointer. I pass alongpointer->head` to this function. And its not working.
insert(pointer->head, value)
As WhozCraig suggests, you can resolve your problem using a pointer to a pointer. Something like this:
void insert(struct smallList **head, char value)
{
*head = newSmallList(value, *head);
}
newSmallList would be something like:
struct smallList *newSmallList(char value, struct smallList *rest)
{
struct smallList *result = malloc(sizeof(struct smallList));
result->next = rest;
result->data = value;
return result;
}
The problem with your current setup is that you are passing the value of the pointer->head field (which happens to be null) to the function, when what you want is to alter what is stored in the field. Here is a program using integers that illustrates a similar mistake:
void setFive(int i)
{
i = 5;
}
int main(void)
{
int myInt = 7;
setFive(myInt);
printf("%d\n", myInt); /* still 7! */
return 0;
}

Retrieve data from a method of another class in C

I'm working on assignment for an operating systems class. We are given code to use to help us with our assignment, but I have little programming experience with C, and I can't figure out how to use it. What I'm trying to do is print the information at the head of the list. The list is a list of structs defined as
typedef struct
{
char name[NAME_MAX];
int lifetime;
} pcb_t;
int
List_head_info ( List_t *list, void **data )
{
int all_ok = 0;
*data = NULL;
if ((list != NULL) && (list->head != NULL)) {
*data = list->head->data;
all_ok = 1;
}
return all_ok;
}
I tried to display them with:
printf("test: %s", List_head_info(&processes, (void *)pcb)->name);
but I am given the error invalid type argument a->a when compiling.
When you call List_head_info(), you will get back two things:
A pointer (void *) to the head data, or NULL.
A status indicating whether the pointer is non-NULL.
If it returns successfully, you can convert (coerce, or cast) the void * to a pcb_t * and then use that to print the data.
How would I do that specifically?
Probably something a bit like this:
List_t list;
...code to initialize and maybe add things to the list...
void *head_data = 0;
if (List_head_info(&list, &head_data))
{
pcb_t *item = (pcb_t *)head_data;
printf("Lifetime: %.2d; Name: %s\n", item->lifetime, item->name);
}
Strictly, the initialization of head_data is superfluous; the code in List_head_info() always sets the value at least once (to NULL or 0) and sometimes twice (the second time to the data component of the head item on the list).
This is 'example code' with enough information in it to compile. I've 'reverse engineered' the list structures enough to make sense; the actual implementation will be different, of course. This compiles cleanly under fairly stringent GCC warning levels, with GCC 4.1.2 and 4.7.0 on Mac OS X 10.7.4. AFAICS, it avoids some complex issues related to 'strict aliasing' which you really don't want to have to worry about at this stage.
#include <stdio.h>
enum { NAME_MAX = 40 };
typedef struct Node Node;
struct Node
{
void *data;
Node *next;
};
typedef struct
{
Node *head;
Node *tail;
} List_t;
typedef struct
{
char name[NAME_MAX];
int lifetime;
} pcb_t;
extern int List_head_info(List_t *list, void **data);
extern void another_func(List_t processes);
void another_func(List_t list)
{
void *head_data = 0;
if (List_head_info(&list, &head_data))
{
pcb_t *item = (pcb_t *)head_data;
printf("Lifetime: %.2d; Name: %s\n", item->lifetime, item->name);
}
}
int
List_head_info ( List_t *list, void **data )
{
int all_ok = 0;
*data = NULL;
if ((list != NULL) && (list->head != NULL)) {
*data = list->head->data;
all_ok = 1;
}
return all_ok;
}

creating a queue of pointers in c

i have a dynamic number of pointers all having the same size. i need to store all the addresses of my pointers in some place like a link List in order to fetch them later on.
my question is what structs should i use. is the following correct:
struct Node{
int *k;
Node*Next;
}
struct LS{
Node*first,*last;
void push(Node*n);
Node* GetFirst();
Node* GetLast();
}
the LS is the linked list that stores Nodes. and a Node is a struct that holds the address of my pointer and a pointer to the next Node.
am i using int *k to store the address of my pointer correctly? should i continue with this implementation or is there any easier way to do this?
this sample code may help you start...
#include <stdio.h>
struct Node{
int *k;
Node *Next;
}* Temp;
struct LS
{
Node *first,*last;
void push(Node *MyNode)
{
MyNode->Next=NULL;
if(empty())
{
first=MyNode;
last=MyNode;
}
else
{
last->Next = MyNode;
last=MyNode;
}
}
Node* front()
{
return first;
}
void pop()
{
free(first->k);
first=first->Next;
}
bool empty()
{
if(first==NULL) return true;
return false;
}
};
int N=10;
int main()
{
LS Q;Q.first=NULL;
for(int i=0;i<3;i++)
{
Node *NewNode= (Node*)malloc(sizeof(Node));
NewNode->k = (int*)malloc(sizeof(int)*N);
for(int k=0;k<N;k++) NewNode->k[k]=i;
Q.push(NewNode);
}
while(!Q.empty())
{
Temp=Q.front();
for(int i=0;i<N;i++) printf("%d ",Temp->k[i]);
printf("\n");
Q.pop();
}
return 1;
}
Yes, your Node struct is correct.
As to whether there is an easier way it depends. If there is a maximum number of pointers that you will need then an array of pointers would be easier. If you can do it in C++ then an STL vector (can use it like an array, but underneath the hood it can grow dynamically as needed) is easier. If you have to do it in C and it has to be dynamic, though, then no, there is not an easier way.
WDM.H (microsoft header) has a bunch of linked list stuff to look at ( http://msdn.microsoft.com/en-us/library/ff547799(VS.85).aspx ) , I've cut and pasted from that, and added a very simple example.
typedef struct _LIST_ENTRY {
struct _LIST_ENTRY *Flink;
struct _LIST_ENTRY *Blink;
} LIST_ENTRY, *PLIST_ENTRY;
typedef struct _MY_THING
{
LIST_ENTRY ListEntry;
ULONG randomdata1;
ULONG randomdata2;
ULONG randomdata3;
ULONG randomdata4;
} MY_THING, *PMY_THING;
#define CONTAINING_RECORD(address, type, field) ((type *)( \
(PCHAR)(address) - \
(ULONG_PTR)(&((type *)0)->field)))
VOID
InsertHeadList(
IN PLIST_ENTRY ListHead,
IN PLIST_ENTRY Entry
)
{
PLIST_ENTRY Flink;
Flink = ListHead->Flink;
Entry->Flink = Flink;
Entry->Blink = ListHead;
Flink->Blink = Entry;
ListHead->Flink = Entry;
}
VOID
InitializeListHead(
IN PLIST_ENTRY ListHead
)
{
ListHead->Flink = ListHead->Blink = ListHead;
}
PLIST_ENTRY
RemoveHeadList(
IN PLIST_ENTRY ListHead
)
{
PLIST_ENTRY Flink;
PLIST_ENTRY Entry;
Entry = ListHead->Flink;
Flink = Entry->Flink;
ListHead->Flink = Flink;
Flink->Blink = ListHead;
return Entry;
}
void main()
{
LIST_ENTRY HeadOfMyList;
MY_THING Thing;
InitializeListHead(&Head);
// example of add thing to list.
InsertHeadList(&HeadOfMyList, &Thing.ListEntry);
// example of removing thing from the list
PLIST_ENTRY listEntry = RemoveHeadList(&HeadOfMyList);
PMY_THING pThing = (PMY_THING) CONTAINING_RECORD(listEntry, MY_THING, ListEntry);
}

Passing argument from incompatible pointer type warning

I've been trying to figure out pointers in C most of today, even asked a question earlier, but now I'm stuck on something else. I've got the following code:
typedef struct listnode *Node;
typedef struct listnode {
void *data;
Node next;
Node previous;
} Listnode;
typedef struct listhead *LIST;
typedef struct listhead {
int size;
Node first;
Node last;
Node current;
} Listhead;
#define MAXLISTS 50
static Listhead headpool[MAXLISTS];
static Listhead *headpoolp = headpool;
#define MAXNODES 1000
static Listnode nodepool[MAXNODES];
static Listnode *nodepoolp = nodepool;
LIST *ListCreate()
{
if(headpool + MAXLISTS - headpoolp >= 1)
{
headpoolp->size = 0;
headpoolp->first = NULL;
headpoolp->last = NULL;
headpoolp->current = NULL;
headpoolp++;
return &headpoolp-1; /* reference to old pointer */
}else
return NULL;
}
int ListCount(LIST list)
{
return list->size;
}
Now in a new file I have:
#include <stdio.h>
#include "the above file"
main()
{
/* Make a new LIST */
LIST *newlist;
newlist = ListCreate();
int i = ListCount(newlist);
printf("%d\n", i);
}
When I compile, I get the following warning (the printf statement prints what it should):
file.c:9: warning: passing argument 1 of ‘ListCount’ from incompatible pointer type
Should I be worried about this warning? The code seems to do what I want it to, but I'm obviously very confused about pointers in C. After browsing questions on this site, I found that if I make the argument to ListCount (void *) newlist, I don't get the warning, and I don't understand why, nor what (void *) really does...
Any help would be appreciated, thanks.
You're getting confused because of multiple typedefs. LIST is a type representing a pointer to struct listhead. So, you want your ListCreate function to return a LIST, not a LIST *:
LIST ListCreate(void)
The above says: ListCreate() function will return a pointer to a new list's head if it can.
Then you need to change the return statement in the function definition from return &headpoolp-1; to return headpoolp-1;. This is because you want to return the last available head pointer, and you have just incremented headpoolp. So now you want to subtract 1 from it and return that.
Finally, your main() needs to be update to reflect the above changes:
int main(void)
{
/* Make a new LIST */
LIST newlist; /* a pointer */
newlist = ListCreate();
int i = ListCount(newlist);
printf("%d\n", i);
return 0;
}

Resources