Trouble dereferencing double pointer - c

I'd like to implement a stack using a linked list.
In order to implement pop() for my stack, I have the caller pass a double pointer (pointer to a pointer) that (eventually) points to the top of my stack ( first entry in linked list ).
The reason why I'm doing it this way is because this way the caller can keep a static pointer to the stack.
My linked list element struct :
struct Element {
int value;
struct Element *next;
};
pop() implementation:
int pop (struct Element **stack) {
int popped_value = *stack->value;
*stack = *stack->next;
return popped_value;
}
The issue I have is trying to dereference the double pointer **stack. This code generates the following error:
error: request for member ‘value’ in something not a structure
error: request for member ‘next’ in something not a structure
In my mind, either *stack->value or **stack.value should work to retrieve popped_value, but I get the identical error.

-> has higher precedence than the dereference operator, so that's like trying to dereference stack->value since the -> gets done first, and * done second. You need to use parentheses:
int popped_value = (*stack)->value;
*stack = (*stack)->next;
Or, as wallyk suggested in the comments, dereference the argument to get a single pointer and use that:
struct Element *sip = *stack;
int popped_value = sip->value;
*stack = sip->next;

-> has higher operator precedence than dereferencing (*) in this line:
*stack->next
You are saying:
*(stack->next)
Which fails since stack->next doesn't make sense.
You want:
(*stack)->next
instead.

Related

How do I access a structure member with a pointer in C?

I am practicing with linklist in C. My objective is that I want to delete a node using a function outside of main.
My plan to accomplish this objective is to access the next pointer without clearing/deleting/freeing the head pointer, but I get an error:
"[Error] request for member 'nextptr' in something not a structure or union"
The code:
void del(struct node **head) {
struct node *temp = *head;
//this is what I believe is wrong, i need to access nextptr of head
*head->nextptr = temp->nextptr->nextptr;
free(temp->nextptr);
temp->nextptr = NULL;
Postfix operators like -> have higher precedence than unary *, so *head->nextptr is parsed as *(head->nextptr) - you're trying to apply the -> operator to head (not *head), which is a pointer to a pointer to a struct type, hence the error.
To fix it, you need to explicitly dereference head before applying the -> operator, so you need to write it as (*head)->nextptr.

Linked List function explanation, subscription of a structure pointer

Programming a simple singly-linked-list in C, I came about this repository on Github: https://github.com/clehner/ll.c while looking for some examples.
There is the following function (_list_next(void *)):
struct list
{
struct list *next; // on 64-bit-systems, we have 8 bytes here, on 32-bit-systems 4 bytes.
void *value[]; // ISO C99 flexible array member, incomplete type, sizeof may not be applied and evaluates to zero.
};
void *_list_next(void *list)
{
return list ? ((struct list *)list)[-1].next : NULL; // <-- what is happening here?
}
Could you explain how this works?
It looks like he is casting a void pointer to a list pointer and then subscripting that pointer. How does that work and what exactly happens there?
I don't understand purpose of [-1].
This is undefined behavior that happens to work on the system where the author has tried it.
To understand what is going on, note the return value of _ll_new:
void * _ll_new(void *next, size_t size)
{
struct ll *ll = malloc(sizeof(struct ll) + size);
if (!ll)
return NULL;
ll->next = next;
return &ll->value;
}
The author gives you the address of value, not the address of the node. However, _list_next needs the address of struct list: otherwise it would be unable to access next. Therefore, in order to get to next member you need to find its address by walking back one member.
That is the idea behind indexing list at [-1] - it gets the address of next associated with this particular address of value. However, this indexes the array outside of its valid range, which is undefined behavior.
Other functions do that too, but they use pointer arithmetic instead of indexing. For example, _ll_pop uses
ll--;
which achieves the same result.
A better approach would be using something along the lines of container_of macro.

How would I declare a new struct in this case?

This is what I have right now for my code (just a simple BST)
typedef struct bsn{
int val;
struct bsn *left, *right;
} bsn_t;
typedef struct bst{
bsn_t *root;
int size;
} bst_t;
My question is that for the functions which I'll use, the input is an address like this
void init( bst_t * tree )
How would I use this? This is what I have right now but I'm not sure if it's correct or not
tree->size = 0;
tree->root = NULL;
Also for other functions like
bool insert( bst_t *tree, int val )
I want to declare a temp node to use. Does this work?
bsn_t temp = (bsn_t *) malloc (sizeof (bsn_t));
And my last question is that how would I check if a node is null or not. I tried
bsn_t visitor = (bsn_t*)malloc(sizeof(bsn_t));
visitor = *tree->root;
Then doing
if (visitor != NULL)
But when I compile it says that
'!=': illegal for struct
Please help..
In your tree, the connections between the nodes and the connection from outside, i.e the root, are all pointers. They point to nodes that are allocated on the heap with malloc.
If you define a local variable like:
bsn_t temp;
you get a node on the stack that will be invalid after the returning from the function. In your case, you should never need to create nodes on the stack. You should work with pointers to nodes throughout, which point to existing nodes, to frshly allocated nodes or to nothing (NULL).
So:
bsn_t *temp = malloc (sizeof (bsn_t));
(I've removed the cast to (bsn_t *). It is strange that in the original code, you have cast the return value from malloc to a pointer type when assigning to a struct.)
As for your second question, your code:
bsn_t visitor = (bsn_t*)malloc(sizeof(bsn_t));
visitor = *tree->root;
is wrong in several places. First, as above, the visitor should be a pointer to a node, not a node struct.
Then the visitor is supposed to travel from the root down the tree. By doing so, it does not create any new nodes, so there is no need to malloc at all. Remember, malloc gives you new memory on the heap, in effect creating a node. The visitor just points to existing objects. One object can have more pointers pointing to them.
Even if malloc were the right ting to do, you shouldn't malloc and then overwrite the pointer that holds the (so far only) handle to the ne memory.
You've also got the * wrong. The visitor is a pointer ans tree->root is a pointer, too, so there's no need to dereference. What you have done is to copy the contents of the root to your local struct.
What you want to do is someting like this:
bsn_t *visitor = tree->root;
while (visitor != NULL) {
// Do stuff
visitor = visitor->right; // or left, whatever
}
The use of asterisks in declaration and use may be confusing. In a declaration, you use a start to make a thing a pointer:
bsn_t node; // uninitialised node struct on the stack
bsn_t *pnode; // uninitialised pointer to node
After that, when you use the pointer variable, the unadorned name refers to the the pointer. An asterisk means that you dereference it to get at what the pointer points to. When you work with structures, you usually won't see many stars, because the -> syntax is preferred, but node->left is essentially the same as (*node).left.
You can't assign memory addresses (The return value from a malloc call) to struct typed variables. You need to assign these to pointer typed variables.
bsn_t *temp = (bsn_t *) malloc (sizeof (bsn_t));
bsn_t *visitor = (bsn_t*)malloc(sizeof(bsn_t));
Then you won't have compile time errors.
How would I use this? This is what I have right now but I'm not sure if it's correct or not
tree->size = 0;
tree->root = NULL;
Yes this is the right way to use it. If you have a pointer you can access the struct elements with(->) operator otherwise, use . (dot) operator.
bsn_t temp = (bsn_t *) malloc (sizeof (bsn_t));
Yes this is the right way as well but you are missing a '*' before temp on left hand side which states that this is a pointer type variable. Remember, it will allocate the object in heap so you have to explicitly free that memory when you no longer need it. Also, note that casting the newly allocated memory to (bsn_t *) is optional, if you don't do, compiler will implicitly do it for you depending upon your l-value type.
bsn_t visitor = (bsn_t*)malloc(sizeof(bsn_t));
Again, it should be bsn_t *visitor on your left hand side.
visitor = *tree->root;
Following that it should be *visitor = *tree->root;
Also, try to make your code more readable by writing *(temp->root) instead of *temp->root.
if (visitor != NULL) Now you should be able to use this since visitor is a pointer now.

Usage of Pointer to Pointers

I was trying to write a pop function which pops a node from a linked list by using a pointer to the head pointer of the linked list
My code was:
struct stack{
char name;
int info;
struct stack *next;
};
typedef struct stack s;
The first POP Function which i wrote was (this is my first time using pointer to pointer)
1) s *pop(s **ps){
s **temp1;
*temp1=NULL;
*temp1=*ps;
*ps=(*ps)->next;
return *temp1;
}
rather this worked
2) s *pop(s **ps){
s *temp2=NULL;
temp2=*ps;
*ps=(*ps)->next;
return temp2;
}
I am getting a segmentation fault for 1,whats going wrong?,Is there a better way to do this?
I used the pointer to pointer method cos i have read pointers are passed by value so even if i change something in pop using temp variable the local change wont affect the actual one
To simplify the issue, let's illustrate using integers and pointers to integers instead of pointers and pointers to pointers:
First fragment:
int pop(int *ps){
int *temp1;
*temp1=0;
*temp1=*ps;
*ps=*ps + 1;
return *temp1;
}
Second fragment:
int pop(int *ps){
int temp1;
temp1=0;
temp1=*ps;
*ps=*ps + 1;
return temp1;
}
In your first code fragment, you are dereferencing an uninitialised pointer. When you try to access *temp1, you will receive an access violation because temp1 is uninitialised and probably points to NULL or some other invalid pointer. In the second fragment, we are not dereferencing it, only assigning to the memory location the compiler assigned to temp1.
The reason ps is a pointer to a pointer (or a pointer to an integer in our illustration) is because we want to change its value outside the function. Whoever calls the pop function will tell us at what location pop should write the new value. We do not have direct access to that variable so the caller needs to pass a pointer to it. Within the pop function, however, we don't need to use pointers to pointers because our local variable is accessible.
In this here:
s **temp1;
*temp1=NULL;
temp1 points nowhere since it is not initialized, but you write NULL to where it points.

placement of unary operator when using pointers in C

I am trying to learn about pointers in C, and don't understand why the unary * operator was appended to the end of the word "node" in the following code snippet:
struct node* CopyList(struct node* head) {
/* code here */
}
From my understanding of pointers, one can create a pointer with a statement like
int *pointerName;
and assign a "pointee" to it with a statement like
pointerName = malloc(sizeof(int));
and then dereference the pointer with a statement like
*pointerName = 4;
which will store the integer value 4 in the 4 bytes of memory (pointee location) which is "pointed to" by the pointerName pointer.
WITH THAT BEING SAID, what does it mean when the * is appended to the end of a word, as it is with
struct node*
???
Thanks in advance!
http://cslibrary.stanford.edu/103/
The location of the * ignores the whitespace between the base type and the variable name. That is:
int* foo; // foo is pointer-to-int
int *bar; // bar is also pointer-to-int
In both cases, the type of the variable is "pointer-to-int"; "pointer-to-int" is a valid type.
Armed with that information, you can see that struct node* is a type, that type being "pointer-to-node-structure". Finally, therefore, the whole line
struct node* CopyList(struct node* head)
means "CopyList is a function taking a pointer-to-struct node (called head) and returning a pointer-to-struct node"
int *pointerName; is the same as int * pointerName; or int* pointerName;. The data type is int* in all those cases. So struct node* is just a pointer to struct node.
struct node* CopyList
To understand better you should read it from right to left. Which says CopyList is a function returning a pointer to node.
You can use '*' either with type or with function name/variable name.But it is suggested to use it with return type while declaring methods, like shown below
struct node* CopyList(struct node* head) {
/* code here */
}
when declaring pointers of a type use * with the variable name. like shown below,
int *ptr;
Declaring in that way increases readability.
For example consider this case,
int* a,b,c;
The above statement is appearing like declaring three pointer variables of base type integer, actually we know that it's equals to
int *a;
int b,c;
Keeping the * operator near the data type is causing the confusion here, So following the other way increases readability, but it is not wrong to use * in either way.
node* means that the following function/variable/structure has type 'pointer to type node'.

Resources