House.Lee
House.Lee

Reputation: 251

*(char**) how to understand this construct?

recently, while reading former's code in my current project, I encounter the problems below:

while implementing the Queue, my former wrote codes like this:

while(uq->pHead)
{
    char *tmp = uq->pHead;
    uq->pHead = *(char **)tmp;
    //...
}

the uq->pHead has definition like:

typedef struct {
        char* pHead;
        //...
} Queue;

Well, I'm quite confused about the usage that "uq->pHead = *(char**)tmp" , could anyone explain it to me in detail?

if we assume that *(uq->pHead) = 32(i.e. ' ') , *(char**)tmp would translate this into pointer-form, but...how could it make sense?

Thanks a lot.

Upvotes: 2

Views: 305

Answers (4)

CodeSun
CodeSun

Reputation: 17

Assume your Queue struct has a object named qa, the address of qa's first data is the same as qa's. In C++, you have many ways to invoke data such as,".","->" . But they are all really use offset just like

`#include<cstdio>        
using namespace std;        
class A        
{        
public:        
    int a;        
    int b;        
};        
int main()        
{        
    A a;        
    printf("%p\n",&a);        
    printf("%p\n",& A::a);        
    printf("%p\n",& A::b);        
    printf("%p\n",&(a.a));        
    printf("%p\n",&(a.b));        
    return 0;        
}`        

You can get what you want from this code.

Upvotes: 0

mohit
mohit

Reputation: 6044

In this queue pHead is pointer to another pHead.More appropriately it can be written as:

 void *pHead;   

Also tmp can be written as:

void *tmp;  
tmp = uq->pHead;  

saves the current pHead pointer to tmp variable.
Now, tmp is casted as (void **) so that tmp is seen as pointing to another pointer.
*(void **) tmp; is the value at tmp, which is also seen as pointer.

uq->pHead = *(void **) tmp;  

So, this increments the pHead to next element.
This statement can also be written as:

uq->pHead = uq->pHead->pHead;  

I am sorry, if i confused you.

Upvotes: 2

Managu
Managu

Reputation: 9039

Let's suppose that we're implementing your Queue as a linked list. We might have:

struct data_type;

struct node
{
    node *next;
    data_type item;
};

struct linked_list
{
    node *pHead;
    // ...
};

To empty the linked list, we might write:

linked_list *uq=...;
while (uq->pHead)
{
    // unlink the first node from the list
    node *tmp = uq->pHead;
    uq->pHead = tmp->next; 

    // do something with that node
    // ...

    // deallocate the node
    free(tmp);
}

Now suppose we don't really care about maintainable code, or are otherwise being lazy. We might instead just figure any pointer would do, and keep the structure for 'node' in our head, and write:

linked_list *uq=...;
while (uq->pHead)
{
    // unlink the first node
    char *tmp = uq -> pHead;     // tmp points to the first 'node'
    uq -> pHead = *(char**)tmp;  // The first thing in a 'node' is a pointer to
                                 // the next node.

    // do something with 'tmp', the now unlinked node
    data_type *item=(data_type*) ( ((char**)tmp) + 1 ); // after the 'next' pointer
                                                        // is the real data.
    // ...

    // free up the node
    free(tmp);
}

Upvotes: 6

D&#233;j&#224; vu
D&#233;j&#224; vu

Reputation: 28840

The Queue struct is likely to be... a queue. And it seems its first element is a pointer to the next or previous item of the queue. It sounds like the coder was not confortable with having to use the type he is being creating - Queue - inside the Queue itself.

A solution for instance was

  typedef struct Queue {
    struct Queue *pHead;
    //...
  } Queue;

Back to your question,

  char *tmp = uq->pHead;

set tmp to the current Queue item (save it for later use)

  uq->pHead = *(char **)tmp;

set the uq->pHead pointer value to the pHead of the current item. Since the coder didn't declare appropriately the pHead ( char * instead of struct Queue * ) it casts the structure pointer ( uq->pHead == tmp ) to char ** and then *(char **) it to retrieve the the first pointer of the structure, that is pHead.

Using my above declaration, the code could have been

  while(uq->pHead)
  {
    Queue *tmp = uq->pHead;
    uq->pHead = tmp->pHead; // or uq->pHead = uq->pHead->pHead
    //... 
  }

Upvotes: 2

Related Questions