【问题标题】:C: sys/queue.h - how to pass a pointer to TAILQ_HEAD() into a function, instead of having TAILQ_HEAD() be global?C: sys/queue.h - 如何将指向 TAILQ_HEAD() 的指针传递给函数,而不是让 TAILQ_HEAD() 成为全局的?
【发布时间】:2018-07-12 05:59:35
【问题描述】:

这里是 C 的新手。我正在使用sys/queue.h 创建一个简单的队列。我在 SO 和 Google 上进行了相当多的搜索,但找不到这个特定问题的解决方案。

这很好用:

#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;
}

我知道通常应该避免使用全局变量。虽然我也知道 TAILQ_HEAD() 是一个宏,所以也许这会改变我对这个问题的看法。无论如何,这不会编译:

#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;
}

当我尝试编译后者时,我收到以下错误。它们没有帮助,因为我无法区分 ‘struct &lt;anonymous&gt; *’‘struct &lt;anonymous&gt; *’

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) {
      ^~~~~~~

我知道 TAILQ_HEAD 的手册页显示您可以定义以下内容:

TAILQ_HEAD(tailhead, entry) head;
struct tailhead *headp;                 /* Tail queue head. */

但我不确定如何处理这个struct tailhead *headp。我尝试将它作为指针传递给&amp;head,如下所示,但这似乎也不起作用:

#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;
}

错误:

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) {
      ^~~~~~~

谁能告诉我我做错了什么,无论是在我的代码中还是在我思考这个问题的方式上?谢谢。

【问题讨论】:

  • 这是在 Linux 中吗?另外我的意思是sys/queue.h 与 Linux 相关吗?我可以在 Windows 中找到它吗?

标签: c queue


【解决方案1】:

我从不使用此队列,但我发现的一种方法是在 q_item 本身中添加 TAILQ_HEAD()。它有助于避免全局使用 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;
}

此外,查看此宏如何扩展可能很有用,只需使用-E 选项编译gcc,您将看到例如TAILQ_HEAD(, qitem) head 扩展为

struct {
       struct q_item *tqh_first; 
       struct q_item **tqh_last; 
 } head;

你也可以在&lt;sys/queue.h&gt;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 */     \
}

这就是为什么您尝试使用 void enqueue(int n, TAILQ_HEAD(, q_item) * head) 不起作用的原因,因为预处理器进行了简单的替换。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-09
    • 2015-04-17
    • 2011-08-25
    • 1970-01-01
    • 1970-01-01
    • 2012-08-08
    相关资源
    最近更新 更多