Pretty new to C here. I'm using sys/queue.h
to make a simple queue. I've searched quite a bit on SO and Google and cannot find a solution to this particular question.
This works fine:
#include <stdio.h>
#include <stdlib.h>
#include <sys/queue.h>
TAILQ_HEAD(, q_item) head;
typedef struct q_item {
int value;
TAILQ_ENTRY(q_item) entries;
} q_item;
void enqueue(int n) {
// enqueue the node with value n
q_item *item;
item = malloc(sizeof(q_item));
item->value = n;
printf("queued %d\n", item->value);
TAILQ_INSERT_TAIL(&head, item, entries);
}
void dequeue() {
q_item *returned_item;
returned_item = TAILQ_FIRST(&head);
printf("dequeued %d\n", returned_item->value);
TAILQ_REMOVE(&head, returned_item, entries);
free(returned_item);
}
int main() {
TAILQ_INIT(&head);
enqueue(1);
enqueue(2);
enqueue(3);
dequeue();
return 0;
}
I know in general global variables should be avoided. Though I also know TAILQ_HEAD() is a macro, so maybe that changes how I should think about this. Anyway, this doesn't compile:
#include <stdio.h>
#include <stdlib.h>
#include <sys/queue.h>
typedef struct q_item {
int value;
TAILQ_ENTRY(q_item) entries;
} q_item;
void enqueue(int n, TAILQ_HEAD(, q_item) * head) {
// enqueue the node with value n
q_item *item;
item = malloc(sizeof(q_item));
item->value = n;
printf("queued %d\n", item->value);
TAILQ_INSERT_TAIL(head, item, entries);
}
void dequeue(TAILQ_HEAD(, q_item) * head) {
q_item *returned_item;
returned_item = TAILQ_FIRST(head);
printf("dequeued %d\n", returned_item->value);
TAILQ_REMOVE(head, returned_item, entries);
free(returned_item);
}
int main() {
TAILQ_HEAD(, q_item) head; // <-- I've moved TAILQ_HEAD into main()
TAILQ_INIT(&head);
enqueue(1, &head);
enqueue(2, &head);
enqueue(3, &head);
dequeue(&head);
return 0;
}
When I try to compile the latter I get the following errors. They are unhelpful since I cannot tell the difference between 'struct <anonymous> *'
and 'struct <anonymous> *'
.
test_tailq_noglobal.c:32:13: warning: passing argument 2 of ‘enqueue’ from incompatible pointer type [-Wincompatible-pointer-types]
enqueue(1, &head);
^
test_tailq_noglobal.c:10:6: note: expected ‘struct <anonymous> *’ but argument is of type ‘struct <anonymous> *’
void enqueue(int n, TAILQ_HEAD(, q_item) * head) {
^~~~~~~
I know the man page for TAILQ_HEAD shows that you can define the following:
TAILQ_HEAD(tailhead, entry) head;
struct tailhead *headp; /* Tail queue head. */
But I am not sure what to do with this struct tailhead *headp
. I have tried passing it as a pointer in place of &head
as follows, but this does not seem to work either:
#include <stdio.h>
#include <stdlib.h>
#include <sys/queue.h>
typedef struct q_item {
int value;
TAILQ_ENTRY(q_item) entries;
} q_item;
void enqueue(int n, struct headname *headp) {
// enqueue the node with value n
q_item *item;
item = malloc(sizeof(q_item));
item->value = n;
printf("queued %d\n", item->value);
TAILQ_INSERT_TAIL(headp, item, entries);
}
void dequeue(struct headname *headp) {
q_item *returned_item;
returned_item = TAILQ_FIRST(headp);
printf("dequeued %d\n", returned_item->value);
TAILQ_REMOVE(headp, returned_item, entries);
free(returned_item);
}
int main() {
TAILQ_HEAD(headname, q_item) head;
struct headname *headp;
TAILQ_INIT(headp);
enqueue(1, headp);
enqueue(2, headp);
enqueue(3, headp);
dequeue(headp);
return 0;
}
Errors:
test_tailq_headp.c: In function ‘dequeue’:
test_tailq_headp.c:21:18: error: dereferencing pointer to incomplete type ‘struct headname’
returned_item = TAILQ_FIRST(headp);
^
test_tailq_headp.c: In function ‘main’:
test_tailq_headp.c:33:13: warning: passing argument 2 of ‘enqueue’ from incompatible pointer type [-Wincompatible-pointer-types]
enqueue(1, headp);
^~~~~
test_tailq_headp.c:10:6: note: expected ‘struct headname *’ but argument is of type ‘struct headname *’
void enqueue(int n, struct headname *headp) {
^~~~~~~
Can someone tell me what I'm doing wrong, either in my code or in the way I'm thinking about this problem? Thanks.
I never work with this queue but one way I found is add TAILQ_HEAD() inside q_item itself. Its help to avoid global usage of head.
#include <stdio.h>
#include <stdlib.h>
#include <sys/queue.h>
typedef struct q_item {
int value;
TAILQ_ENTRY(q_item) entries;
TAILQ_HEAD(, q_item) head;
} q_item;
void enqueue(int n, q_item *q) {
// enqueue the node with value n
q_item *item;
item = malloc(sizeof(q_item));
item->value = n;
printf("queued %d\n", item->value);
TAILQ_INSERT_TAIL(&q->head, item, entries);
}
void dequeue(q_item *q) {
q_item *returned_item;
returned_item = TAILQ_FIRST(&q->head);
printf("dequeued %d\n", returned_item->value);
TAILQ_REMOVE(&q->head, returned_item, entries);
free(returned_item);
}
int main() {
q_item q;
TAILQ_INIT(&q.head);
enqueue(1, &q);
enqueue(2, &q);
enqueue(3, &q);
dequeue(&q);
dequeue(&q);
return 0;
}
Also it may be useful to look how this macros expand, just compile with gcc
using -E
option, and you will see that for example TAILQ_HEAD(, qitem) head
expand to
struct {
struct q_item *tqh_first;
struct q_item **tqh_last;
} head;
Also you can find it in <sys/queue.h>
header
/*
* Tail queue definitions.
*/
#define TAILQ_HEAD(name, type) \
struct name { \
struct type *tqh_first; /* first element */ \
struct type **tqh_last; /* addr of last next element */ \
}
that's why your try with void enqueue(int n, TAILQ_HEAD(, q_item) * head)
didn't work because preprocessor makes simple substituion.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.