title: C: sys/queue.h - how to pass a pointer to TAILQ_HEAD() into a function, instead of having TAILQ_HEAD() be global?
body: <p>Pretty new to C here. I'm using <code>sys/queue.h</code> to make a simple queue. I've searched quite a bit on SO and Google and cannot find a solution to this particular question.</p>
  
  <p>This works fine:</p>
  
  <pre class="lang-c prettyprint-override"><code>#include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;sys/queue.h&gt; 
  
  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-&gt;value = n;
      printf("queued %d\n", item-&gt;value);
      TAILQ_INSERT_TAIL(&amp;head, item, entries);
  }
  
  void dequeue() {
      q_item *returned_item;
      returned_item = TAILQ_FIRST(&amp;head);
      printf("dequeued %d\n", returned_item-&gt;value);
      TAILQ_REMOVE(&amp;head, returned_item, entries);
      free(returned_item);
  }
  
  int main() {
  
      TAILQ_INIT(&amp;head);
  
      enqueue(1);
      enqueue(2);
      enqueue(3);
  
      dequeue();
  
      return 0;
  }
  </code></pre>
  
  <p>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:</p>
  
  <pre class="lang-c prettyprint-override"><code>#include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;sys/queue.h&gt; 
  
  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-&gt;value = n;
      printf("queued %d\n", item-&gt;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-&gt;value);
      TAILQ_REMOVE(head, returned_item, entries);
      free(returned_item);
  }
  
  int main() {
  
      TAILQ_HEAD(, q_item) head; // &lt;-- I've moved TAILQ_HEAD into main()
      TAILQ_INIT(&amp;head);
  
      enqueue(1, &amp;head);
      enqueue(2, &amp;head);
      enqueue(3, &amp;head);
  
      dequeue(&amp;head);
  
      return 0;
  }
  </code></pre>
  
  <p>When I try to compile the latter I get the following errors. They are unhelpful since I cannot tell the difference between <code>‘struct &lt;anonymous&gt; *’</code> and <code>‘struct &lt;anonymous&gt; *’</code>.</p>
  
  <pre><code>test_tailq_noglobal.c:32:13: warning: passing argument 2 of ‘enqueue’ from incompatible pointer type [-Wincompatible-pointer-types]
        enqueue(1, &amp;head);
                   ^
  test_tailq_noglobal.c:10:6: note: expected ‘struct &lt;anonymous&gt; *’ but argument is of type ‘struct &lt;anonymous&gt; *’
       void enqueue(int n, TAILQ_HEAD(, q_item) * head) {
        ^~~~~~~
  </code></pre>
  
  <p>I know the man page for TAILQ_HEAD shows that you can define the following:</p>
  
  <pre><code>TAILQ_HEAD(tailhead, entry) head;
  struct tailhead *headp;                 /* Tail queue head. */
  </code></pre>
  
  <p>But I am not sure what to do with this <code>struct tailhead *headp</code>. I have tried passing it as a pointer in place of <code>&amp;head</code> as follows, but this does not seem to work either:</p>
  
  <pre class="lang-c prettyprint-override"><code>#include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;sys/queue.h&gt; 
  
  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-&gt;value = n;
      printf("queued %d\n", item-&gt;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-&gt;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;
  }
  </code></pre>
  
  <p>Errors:</p>
  
  <pre><code>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) {
        ^~~~~~~
  </code></pre>
  
  <p>Can someone tell me what I'm doing wrong, either in my code or in the way I'm thinking about this problem? Thanks.</p>