Please find the code snippet as shown below:
#include <stdio.h>
int My_func(int **);
int main()
{
int a =5;
int *p = &a;
My_Func(&p);
printf("The val of *p is %d\n,*p);
}
void My_Func(int **p)
{
int val = 100;
int *Ptr = &val;
*p = Ptr;
}
How does by using a double pointer as a argument in my_Func function and making change of value reflects the same in the main function but if we use a single pointer in My_Func does not change the value in main?Please do explain me with examples if possible
Advanced thanks
Maddy
int **p is a pointer to a pointer-to-int. My_Func(int **p) works by changing the value of integer that the pointer-to-int points to i.e. int a.
Without changing the implementation, the function will not work with a pointer-to-int parameter int *p as there is a second level of indirection. In addition, you're setting the value to a local variable that is created on the stack. When the function is completed the memory used for the variable will be reclaimed, therefore making the value of a invalid.
void My_Func(int **p)
{
int val = 100; // Local variable.
int *Ptr = &val; // This isn't needed.
*p = Ptr;
} // val dissapears.
Remove the second level of indirection and copy val by value instead of pointing to it:
#include <stdio.h>
void My_Func(int *p)
{
int val = 100;
*p = val;
}
int main(void)
{
int a = 5;
My_Func(&a);
printf("The val of a is %d\n", a);
return 0;
}
In short, in C when you pass something as a parameter, a copy will be passed to the function. Changing the copy doesn't affect the original value.
However, if the value is a pointer, what it points to can be changed. In this case, if you want to affect the pointer, you need to pass a pointer to it down to the function.
Use it in the function declaration:
void func(int *p)
{
int val =100;
int *temp=&val;
p=temp;
}
p starts pointing to another address i.e. address of val. So it will print the value 100.
Important note: Try it in your downloaded compiler (always in case of pointers) not in the online compiler. The online compiler doesn´t keep track of lost addresses in stack.
You are assigning the address of local variable, which will soon disappear when My_Func returns. You can use following in your code. However you can do the same thing just by using single pointer, double pointer is not required in this example.
void My_Func(int **p)
{
int val = 100;
int *Ptr = &val;
**p = *Ptr;
}
Related
This variable num remains at 0. I suspect this is because I am passing in a NULL pointer, but I am constrained to the main (and parameters) as is. How do I adjust the content of the helper function to update num correctly?
int main(void) {
int * num_results = NULL;
int num = 4;
set(num_results, num);
printf(“%d\n”, *num_results);
return 0;
}
void set(int * results,num){
num_results = malloc(sizeof(int));
*num_results = num;
}
I'm going to guess what you really mean with your question and try to give a decent answer.
I guess you want to change num_results to be equal to num by passing it to the function set as a pointer, and I can see a few mistakes you've made:
You probably have this in your full code, but don't forget to #include <stdio.h> to use printf() and to #include <stdlib.h> to use malloc()
Your function set() should be declared before main(), you can do this by declaring a prototype before main() or simply defining the set() function before main().
Now let's go to your solution: you want to pass the num_results as a parameter to a function, allocate some memory and assign the address to num_results and then update the value to the one in num.
When you pass an int * as a parameter, I guess you already know that by passing int you are simply giving a copy of what is inside an int variable. This works the same way with an int *, you are not passing a reference to num_results so that you can update the address of the pointer, you are passing a copy of the current address, NULL, which will not be modified. What could be modified is what is inside of the current address, but the current address is NULL, so not can really be modified.
Since you want to allocate memory and assign its address to num_results, you must pass a pointer to a pointer, so you are passing the address of where your int* variable is being kept and where you can actually change it.
This way, your function should look like void set(int ** results, int num) and you should call it with set(&num_results, num), so you are passing a reference to num_results, where you can change the address it points to, currently NULL and then the address returned by malloc().
You'd also have to change the body of your function, because you're now using an int **, you want to assign the new address to *results, because results == &num_results, and assign num to **results, because *results = num_results.
I hope my explanation is not very confusing and hopefully someone can explain it better with another answer or by editing mine. Final code:
#include <stdio.h>
#include <stdlib.h>
void set(int ** results, int num){
*results = malloc(sizeof(int));
**results = num;
}
int main(void) {
int * num_results = NULL;
int num = 4;
set(&num_results, num);
printf("%d\n", *num_results);
return 0;
}
set(num_results, num);
Here NULL is getting passed to results variable in set(), when you allocate memory to results, NULL is getting replaced by valid memory address, but you need to understand it will be held in results variable only as its a local variable to set()
You should either pass address of num_results to set() so that memory allocated in set() is retained in main(), or just allocate memory to num_results in main function then pass it to set() as done below:
#include <stdio.h>
int main() {
int *num_results = NULL;
int num = 4;
num_results = malloc(sizeof(int));
set(num_results, num);
printf("%d\n", *num_results);
return 0;
}
void set(int *results,int num){
*results = num;
}
Another example would be:
#include <stdio.h>
#include <stdlib.h>
void set(int **r, int num);
int main() {
int *num_results = NULL;
int num = 4;
/*num_results = malloc(sizeof(int));*/
set(&num_results, num);
printf("%d\n", *num_results);
return 0;
}
void set(int **results,int num){
*results = malloc(sizeof(int));
*(*results) = num;
}
How do I adjust the content of the helper function to update num correctly?
That seems the wrong question, as your set() function seems intended to copy the value of num elsewhere, not to update num itself.
One of your problems is where to copy it. Presently, you allocate some memory for that dynamically, and copy it there. That's fine as far as it goes, but the pointer to the allocated memory is not conveyed back to the caller. This is because all C functions pass arguments by value, and in particular, your main() passes the first argument of set() by value (a value of type int *). Modifying the function's copy does not affect its caller's copy -- that's what pass-by-value is all about.
You may be overlooking a simple fact: dynamic allocation is not the only way to obtain a valid pointer value, nor even the the most important or common. When you see a pointer, you should not automatically go looking for malloc(). You can very easily get a pointer from an array, but perhaps even more importantly, you can get a pointer value by applying the address-of operator (&).
For your set() function to do work that its caller can see without resorting to global variables or changing its signature, the caller must pass as the first parameter a valid pointer to an object that the caller can access, such as one of its own local variables. The pointer is passed by value so the function gets a copy, but it's a copy: it points to the same object that the caller's pointer did. The set() function can therefore modify the pointed-to object via its copy of the pointer to it.
So suppose your main() declared its own local variable result, an int. What do you suppose it could do with &result?
In your helper function you should refer to the first parameter name results instead of num_results. Your helper function should be like:
void set(int * results, int num){
results = malloc(sizeof(int));
*results = num;
}
Your code won't compile. Compiler error messages will tell you how to fix them. Here is a fixed one.
#include<stdlib.h>
#include<stdio.h>
int * num_results = NULL;
void set(int * results, int num){
num_results = malloc(sizeof(int));
*num_results = num;
}
int main(void) {
int num = 4;
set(num_results, num);
printf("%d\n", *num_results);
return 0;
}
For the sake of learning it, you can look at the compilation error messages here and try to fix it by yourself:https://segfault.stensal.com/a/XWfv8rxCJHVtAuRQ
Disclaimer: I built stensal.io as a tool to catch memory issues.
Why in this code the pointer shifts to another location:
#include <stdio.h>
void f(int *p)
{
int j=2;
p=&j;
printf("%d\n%p\n%d\n",*p,&j,p);
}
int main(void)
{
int *q;
int m=98;
q=&m;
f(q);
printf("%p ",q);
return 0;
}
Output:
2
0x7ffff5bf1bcc
0x7ffff5bf1bcc
0x7ffff5bf1bc8
I understand that when the function f() is done with printing value of j and address of j the memory occupied by j goes back to the stack but IMO p should continue pointing that location even after the function is over & it should be printing the same address in main as well. What is wrong with this?
Considering you meant printf("%p ", (void *)q); in the actual code,
No, function argument(s) in C is (are) passed by value. It won't reflect the changes made to the parameter into the actual arguments used (in function call) themselves.
To put it into other words, the function parameters are local to the function (call) scope, any changes made to them won't be reflected to the actual arguments.
So, if you need to change a pointer, you need to pass a pointer to the pointer which needs to be changed.
Consider a rather light-hearted but realistic scenario.
void f (int x) { x = 10; }
int main(void) { f(5); printf ("%d", 5); return 0;}
Now, do you expect it to print 10?
That said, an advice. Always cast the argument to %p conversion specifier to (void *) (if it is not already). printf() is a variadic function and for pointers, no default argument promotion happens, so the supplied argument type needs to match the expected type, explicitly. Otherwise, technically it is undefined behavior.
Learn the difference between Pointers and Pointers to pointers - the pointer passed p is no doubt good to change the value of the variable it is pointing to (m), but to change the memory location it is pointing to - you need a pointer to pointer.
Expanding on top of what #SouravGhosh said, when you pass in a pointer to an int you are making a copy of the pointer. If you wanted to change the pointer you need to be doubly indirect and pass in a pointer to a pointer to an int. The first pointer is copied and you can directly affect the second pointer.
void f(int ** p)
{
int j = 2;
*p = &j;
printf("%d\n%p\n%p\n",*p,&j,p);
}
int main(void)
{
int ** q = (int **)malloc( izeof(int *));
int m = 98;
*q = &m;
f(q);
printf("%p ",q);
free(q);
return 0;
}
And the output is
2
0xffffcbcc
0xffffcbcc
0xffffcbcc
If you do this you'll see that it never changes:
#include <iostream>
#include "Header2.h"
#include "header1.h"
#include <stdio.h>
void f(int *p)
{
int j = 2;
p = &j;
printf("%d\n%p\n%p\n", *p, &j, p);
}
int main(void)
{
int *q;
int m = 98;
q = &m;
printf("Value of pointer q before calling f() =%p ", q);
f(q);
printf("Value of pointer q after calling f() =%p ", q);
return 0;
}
The value in the printf hasn't changed after applying the void function f, which is confusing me. It's basic stuff revolving pointers. The exact question is: Why isn't the end value 2 instead of 1?
int a=1, b=2;
void f(int* p) {
p=&b;
}
int main() {
int *p=&a;
f(p);
printf("%d\n", *p);
}
The *p value in main remains 1, and that's what's confusing me.
You need to dereference p and remove the & address operator from b
This assigns the value of b to the address where p points to:
void f(int* p)
{
*p = b;
}
The reson why it printed 1 and not e.g. the address of b is that you assigned: p = &b which just assigns the address of b to the local pointer variable p. This means it does not point to a anymore here. But since this was just a local copy it didn't change the value of the p you passed in main().
This makes it a little more obvious:
void f(int* ptr)
{
// assign a value
*ptr = 1337;
}
int main()
{
int local_integer = 666;
// prints "666"
printf("%d\n", local_integer);
f(&local_integer);
// prints "1337"
printf("%d\n", local_integer);
}
In your code you define a pointer to int on the stack. Its value is the same as the pointer in the main() function which happens to point to the ąddress of the variable a. Then you change its value (so the pointer on the stack now points to b) then you just drop that pointer.
void f(int* p) {
p=&b;
}
That is why if you dereference the pointer in main it still points to the address of the int variable a.
I want to pass a pointer as a size element of an array
example:
void hello(int array1[how can i refer pointer "ptr" here][2])
{
// i want to access the array used in the main() here
printf("hi");
}
int main()
{
int c=5;
int *ptr=&c;
a[*ptr][2];
a[0][1]=0;
a[0][2]=4;
}
I apologize for not being clear with my question here , i want to access the array used in the main() function in my hello() function.
You will have to use the value pointed to by the pointer:
a[*ptr][2];
ptr is the address pointed to by the pointer not the value stored there. You use the dereference operator * to get the value.
Of course, ptr is not of type int, it's of type int * (integer pointer). An array subscript must be of type int.
Maybe what you want is a[*ptr][2].
You need to deference the pointer by using *ptr so
int c = 5;
int *ptr = &c;
a[*ptr][2];
otherwise you are not using the value of ptr you are using its address in memory which returns an error.
Use the dereference operator *:
a[*ptr][2];
The expression *ptr tells the compiler to use the value pointed to by ptr.
As for your updated question, that's not possible. But it's not needed either, as it's passed as a pointer anyway.
When declaring a function, this:
void foo(int a[5][5])
is the same as this:
void foo(int a[][2])
And also the same as this:
void foo(int (*a)[2])
It has pretty much been answered already, you can't call an adress in the array a[0x3950f2][2]
Always use the pointer* to get the position in the array a[*ptr][2] to get the expected value - in this case: a[*ptr][2] == a[5][2]. You may read this.
Edit to your updated question: You can't to this. You can use the pointer when you call the function or when using the variable in the function.
Your second edit:
void hello(int **array1)
{
// i want to access the array used in the main() here
printf ("hi");
a[0][0] = 24;
}
int main()
{
int c = 5;
int *ptr = &c;
int **a;
a[*ptr][2];
a[0][1] = 0;
a[0][2] = 4;
hello (a);
return 0;
}
Something I stumbled upon and made me wonder.
Why does this work?
void foo (int* a)
{
int x = 3;
*a = x;
}
int main()
{
int a;
foo(&a);
return 0;
}
But this causes a segmentation fault (both on Visual Studio 2008 and gcc)?
void foo (int* a)
{
int x = 3;
*a = x;
}
int main()
{
int* a;
foo(a);
return 0;
}
Is it something defined in the language or just an implementation issue?
When you declare
int* a;
You are declaring a pointer variable a but you are not making it point to anything. Then in the function, you do
*a = x;
Which dereferences the pointer and tries to assign what it points to the value of x. But since it doesn't point to anything, you get undefined behaviour, manifested in a segmentation fault.
You should do this:
int i; // the actual integer variable
int* a = &i; // a points to i
The difference between that and the first one is that int a; declares a real integer variable, then you take its address with &a and passes it to the function. The pointer a inside the function foo points to the variable a in main, and so dereferencing it and assigning to it is perfectly fine.
int a;
Assigns memory as soon as you declare it but this not the case with int *a;
int *a;
is pointer declaration (MEMORY not yet allocated for that).
int *a = (int*)malloc(sizeof(int)); // allocate memory