Usage of Pointer to Pointers - c

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.

Related

variable should not reset when calling the function again?

I want the value of a pointer variable to be initialized to NULL at the start of the execution. This variable is used in a function and its value may also get changed within the function. But I do not want the value of this variable to reset to NULL whenever a function call is made. Instead, its value should be equal to the updated value from its previous function call. Cannot use global variables.
void function(struct node *variable) {
// changes value of pointer variable to something else
variable = something;
}
void another_function(void) {
// have to be initialised before passing in as argument or else will raise error
struct node *variable = NULL;
function(variable);
}
// then calling this function multiple times in main
another_function();
another_function();
help would be much appreciated.
Firstly, the pointer variable variable is local to another_function. It does not live outside of this scope.
Secondly, when you pass it to function, the variable parameter of that function is also local to that function. You immediately assign a value to that local variable, but that doesn't change the variable you passed in.
You can use the static keyword when declaring your initial pointer variable.
It will only be initialized when first encountered during the execution.
But as for now, your code will probably not do what you intend it to do.
The pointer variable in function is local and will have no effect on the value of variable in another_function.
You should use a pointer of pointer (also called a double-pointer or a nested pointer) for this effect.
Here is an example of how to use a double-pointer :
struct node {
int value;
};
void function(struct node** variable) {
if(*variable == NULL) {
*variable = (struct node*)malloc(sizeof(struct node));
(*variable)->value = 1;
}
printf("Value of variable is %d\n", (*variable)->value);
// Creating another struct node just for the demonstration
struct node* newnode = (struct node*)malloc(sizeof(struct node));
newnode->value = (*variable)->value + 1;
*variable = newnode;
}
void another_function() {
static struct node* variable = NULL;
function(&variable);
}
Basically, you pass the address of a pointer (located on the stack, which will always have a memory address) which let you modify the content of this pointer (a memory address on the heap) in the receiving function.
When you are dereferencing variable in function, what you get is not a value but another pointer.
Also parenthesis are important in this case.
Nested pointers can really be confusing, I hope that my explanation is somewhat clear.
To really understand how it works you need to understand what it's on the stack and what it's on the heap. But maybe this is an explanation for another time.
Of course, there is no memory management in this example and what I wrote contains memory leaks from all struct node that never are deallocated.
You should figure out how to do it depending on your program architecture.

Does passing "pointer to structure" to a function create local copies of it in C?

I have a structure like this
struct node
{
int data;
struct node* next;
};
Which I use to create singly linked list.
I created other functions like
int push(struct node* head,int element);
which pushes data onto stack created using node structs.
The function then tries to update the struct node* head passed to it using code(it does other things as well)
head=(struct node*)malloc(sizeof(struct node));
The call is made as such
struct node* stack;
push(stack,number);
It looks like this code created copy of the pointer passed to it. So I had to change the function to
int push(struct node** head,int element)
and
*head=(struct node*)malloc(sizeof(struct node));
The call is made as such
struct node* stack;
push(&stack,number);
So my question is, what was the earlier function doing? Is it necessary to pass struct node** to the function if I want to update original value of pointer or is my approach wrong?
Sorry I cannot provide complete code as it is an assignment.
C always passes by value. To change a variable passed to a function, instead of passing the variable itself, you pass a reference(its address).
Let's say you're calling your function with the old signature
int push(struct node* head,int element);
struct node *actual_head = NULL;
push(actual_head, 3);
Now before calling push, your variable actual_head will have value as NULL.
Inside the push function, a new variable head will be pushed to stack. It will have the same value as passed to it, i.e. NULL.
Then when you call head = malloc(...), your variable head will get a new value instead of actual_head which you wanted to.
To mitigate the above, you'll have to change the signature of your function to
int push(struct node** head,int element);
struct node *actual_head = NULL
push(&actual_head, 3);
Now if you notice carefully, the value of actual_head is NULL, but this pointer is also stored somewhere, that somewhere is its address &actual_head. Let's take this address as 1234.
Now inside the push function, your variable head which can hold the address of a pointer(Notice the two *), will have the value of 1234
Now when you do *head = malloc(...), you're actually changing the value of the object present at location 1234, which is your actual_head object.
C always passes parameters by value (i.e., by copying it). This applies even to pointers, but in that case, it is the pointer itself that is copied. Most of the times you use pointers, that is fine, because you are interested in manipulating the data that is pointed to by the pointer. However, in your situation, you want to modify the pointer itself, so you do indeed have to use a pointer to a pointer.
Yes.
The first version of your program was passing the pointer by value. Although it passed an address (held by the pointer to struct) it didn't pass the pointer's address - necessary to update the value.
Whenever you want to update a variable's value you must pass the variable's address. To pass a pointer address, you need a parameter pointer to pointer to type.
In your case, pointer to pointer to struct node.
The code is not doing what you think but not because it creates a copy of the node, it creates a copy of the pointer.
Try printing
fprintf(stdout, "Address of head: %p\n", (void *) head);
both, inside push() and in the caller function.
The pointer you pass in and the parameter have different addresses in memory although they both point to the same address, storing the result of malloc() in it doesn't persist after the funcion has returned.
You need to pass a pointer to the pointer like this
int push(struct node **head, int element)
{
/* Ideally, check if `head' is `NULL' and find the tail otherwise */
*head = malloc(sizeof(**head));
if (*node == NULL)
return SOME_ERROR_VALUE;
/* Do the rest here */
return SOME_SUCCESS_VALUE_LIKE_0;
}
And to call it, just
struct node *head;
head = NULL;
push(&head, value);
/* ^ take the address of head and pass a pointer with it */
of course, the push() implementation should be very differente but I think you will get the idea.
Everything everybody has said is absolutely correct in terms of your question. However, I think you should also consider the design. Part of your problem is that you are conflating the stack itself with the internal structures needed to store data on it. You should have a stack object and a node object. i.e.
struct Node
{
int data;
struct Node* next;
}
struct Stack
{
struct Node* head;
}
Your push function can then take a pointer to the Stack without any double indirection. Plus there is no danger of pushing something on to a node that is in the middle of the stack.
void push(struct Stack* stack, int value)
{
struct Node* node = malloc(sizeof node);
node->data = value;
node->next = stack->head;
stack->head = node;
}
The function
int push(struct node* head,int element) {
head=(struct node*)malloc(sizeof(struct node));
}
allocate some memory and throw it away (cause memory leak).
Passing “pointer to structure” to a function do create local copies of it.
It is necessary to pass struct node** to the function if you want to update original value of pointer. (using global variables is generally considered as a bad idea)
When you pass stack to your function push(struct node* head,int element)
and do
head=(struct node*)malloc(sizeof(struct node));
The pointer head will update to the memory allocated by malloc() and stack is unaware of this memory as you just passed the value.(which is uninitialized here)
When you pass the address then you have a pointer to pointer which makes the changes inside push() to be reflected on stack
So my question is, what was the earlier function doing?
Your earlier function was defined to receive a pointer to an object. You passed your function an uninitialized struct node pointer. A function can't do anything with a value representing an uninitialized pointer. So your function was passed garbage, but no harm was done because your function immediately ignored it by overwriting with a pointer to allocated memory. Your function is not using the value you passed for anything except temporary local storage now. Upon return from your function, your parameters to the function are thrown away (they are just copies), and the value of your stack variable is as it was before, still uninitialized. The compiler usually warns you about using a variable before it is initialized.
By the way, the pointer value to the allocated memory was also thrown away/lost upon function return. So there would now be a location in memory with no reference and therefore no way to free it up, i.e., you have a memory leak.
Is it necessary to pass struct node** to the function if I want to update original value of pointer or is my approach wrong?
Yes, it is necessary to pass the address of a variable that you want filled in by the function being called. It must be written to accept a pointer to the type of data it will supply. Since you are referencing your object with a pointer, and since your function is generating a pointer to your object, you must pass a pointer to a pointer to your object.
Alternatively, you can return a pointer as a value from a function, for example
struct node * Function() { return (struct node *)malloc(sizeof(struct node)); }
The call would be...
struct node *stack;
stack = Function();
if(stack == NULL) { /* handle failure */ }
So, your approach is not wrong, just your implementation (and understanding) need work.

Linked List Stack in C

I am looking at the following paragraph in the book "Programming Interviews Exposed" in reference to the implementation of a linked list stack in C:
typedef struct Element {
struct Element *next;
void *data;
} Element;
void push( Element *stack, void *data );
void *pop( Element *stack );
Now consider what will happen in these routines in terms of proper
functionality and error handling. Both operations change the first
element of the list. The calling routine’s stack pointer must be
modified to reflect this change, but any change you make to the
pointer that is passed to these functions won’t be propagated back to
the calling routine. You can solve this problem by having both
routines take a pointer to a pointer to the stack. This way, you can
change the calling routine’s pointer so that it continues to point at
the first element of the list. Implementing this change results in the
following:
void push( Element **stack, void *data );
void *pop( Element **stack);
Could someone explain, in different words, why we need to use a double pointer here? I'm a bit unsure about the explanation provided.
It is similar to the famous swap() function in C.
Case 1:
void swapFails(int x, int y) {
int temp = x;
x = y;
y = temp;
}
Case 2:
void swapOk(int *x, int *y) {
int temp = *x;
*x = *y;
*y = temp;
}
and we invoke swap like this:
int x = 10;
int y = 20;
Case 1:
swapFails(x, y);
Case 2:
swapOk(&x, &y);
Remember, we wanted to CHANGE the values of x and y. For CHANGING values of a datatype, we need pointers. Take this to the next level for pointers. For CHANGING values of a pointer, we would need double pointers.
For Stack using linked list:
If you push values 10, 20 and 30, they are stored like this:
top --- bottom
30 -> 20 -> 10
So you see every time you push or pop values from the stack, which is a linked list, the top or the first node of the linked list changes. Hence you need double pointers.
The first version sends a copy of the pointer, if it's changed inside the function then the local copy would only be changed, when the function returns to the caller the caller still has a pointer to the old address.
Element *stack =...
push (stack)
void push( Element *stack, void *data ) {
stack = ... // this changes the local pointer allocated on the function's stack
}
//call returns
stack //still points to old memory
The second version, however, passes a pointer to the stack pointer, so when that is changed, it changes the stack pointer in the calling function.
In C everything is passed by value, let's say that I have this function:
void foo(void* ptr)
{
ptr=NULL;
}
If you call this method in the main, the pointer that you pass will not be NULL (unless it wat already NULL).Because a copy of the pointer is made before passing it to the function.So if you want to modify it's value, you have to pass a double pointer:
void foo(void** ptr)
{
*ptr=NULL;
}
The same is valid for the stack, of which you want to modify the value.
With the single-pointer signature you can imagine using the code as follows
Element *myStack = NULL ;
.... bla bla bla ....
push(myStack, something);
Then in the push call you're telling the stack implementation where the old head element of the stack was, but there's no way for the implementation of push to tell you where the new head is. It cannot change your myStack variable, because parameter passing in C is always by value -- i.e., the push function get told what the value of myStack happens to be, but get no chance to change the caller's variable.
In order for things to work, you need to tell the push primitive the address of your local variable that it needs to change:
....
push(&myStack, something);
and since myStack itself has type Element *, a pointer to the myStack variable has type Element **.

structure and linked list

struct node
{
int info;
struct node *link;
}*start;
void main()
{
struct node*tmp,*q;
tmp=(struct node*)malloc sizeof(struct node);
}
now my first question is when we declare structure is any struct type node is created in memory?
second question is ,if yes then here i take a start pointer which is pointing to struct type node so without specifying the address of struct node to start pointer how start pointer pointing the struct type node which is created during declaration plz clear me this how internally this is happening i have lot of confusion on that
third question is initially tmp and q pointer variable all are pointing towards the same struct node
plz expalin the concept malloc and calloc how internally they create node
thx for helping me out
You can declare a structure type without declaring any variables. However, your code defines a pointer variable, start.
The variable start is initialized to 0, so it is not pointing to anything.
The variables tmp and q are not initialized at all and cannot be safely used until assigned a value. You initialize tmp in the next line; q is still uninitialized.
malloc() provides space for the pointer to point to; it does not initialize that space. The value in tmp->info is indeterminate; the value in tmp->link is indeterminate too. If you had used calloc(), then tmp->info would be zero and tmp->link would be null (on all practical systems — theoretically, there could be a system where tmp->link was not properly initialized).
Finally, note that void main() is bad. The C standard says that the return type of main() should be int. Further, unless you've got a C99 or later compiler, you should include return(0); or equivalent as the last line in main() — or a call to exit().

double pointer question in C (single pointer for next, but double pointer for prev)

In the code of table.h for mysql. There are the following code
typedef struct st_table_share
{
...
struct st_table_share * next, /* Link to unused shares */
**prev;
in the text book, we usally have
sometype *next, *prev;
but here it use **prev instead of *prev. What the reason to use double pointer for prev?
It's not pointing to the previous structure, as next is, it's pointing to the pointer that's pointing to this structure.
The benefit of doing this is that it can point to either the 'next' member of the preceding structure, or it can point to the actual head pointer itself - in the case where this is the first item in the list. This means that removing the item involves "*prev = next" in both cases - there's no special case for updating the head pointer.
The downside is that you can't (easily) use it to traverse the structure backwards; so it's really designed to optimize the case where you only care about traversing forwards, but want to easily remove an arbitrary node.
it is not a "double pointer" as you mention. rather it is referred to as "de-referencing".
int x = 10;
int* prev = &x;
*prev is the address of variable x.
now lets say you need to pass the address of the pointer variable prev to another function named foo which accepts an address of a pointer as its parameter (pointer to a pointer).
void function foo(int** ptr)
{
prinft("%p", ptr); //this would print the address of prev
printf("%p", *ptr); //this would print the value (the address of x) contained inside address contained inside ptr.
printf("%d", **ptr); //this would print the value (the value of x, 10) contained at the address(address of x) contained inside address (address of prev) contained inside ptr
}

Resources