This question already has an answer here:
Dynamic memory access only works inside function
(1 answer)
Closed 3 years ago.
The following C snippet:
[...]
void f1(void* a){
printf("f(a) address = %p \n",a);
a = (void*)(int*)malloc(sizeof(int));
printf("a address = %p \n",a);
*(int*)a = 3;
printf("data = %d\n",*(int*)a);
}
void f(void){
void* a1=NULL;
printf("a1 address = %p \n",a1);
f1(a1);
printf("a1 address = %p \n",a1);
printf("Data.a1 = %d\n",*(int*)a1);
}
[...]
results in
a1 address = (nil)
f(a) address = (nil)
a address = 0xb3f010
data = 3
a1 address = (nil)
Segmentation fault (core dumped)
Why doesn't a1 keep the address that has been assigned to it in the function?
As this is C, you cannot pass the pointer by reference without passing in a pointer to the pointer (e.g., void ** rather than void * to point to the pointer). You need to return the new pointer. What is happening:
f(a1);
Pushes the value of the pointer (NULL) as the stack parameter value for a. a picks up this value, and then reassigns itself a new value (the malloced address). As it was passed by value, nothing changes for a1.
If this were C++, you could achieve what you want by passing the pointer by reference:
void f(void *&a);
Passing a pointer to a1 to your function, you can't change where a1 points. The pointer is passed by value, so in f1 you're only changing a copy of the address held by a. If you want to change the pointer, i.e. allocate new memory for the pointer passed in, then you'll need to pass a pointer to a pointer:
void f1(void **a)
{
// ...
*a = malloc(sizeof(int));
// ...
To change a variable via a function call, the function needs to have reference semantics with respect to the argument. C doesn't have native reference variables, but can implement reference semantics by means of taking addresses and passing pointers.
Generally:
void mutate_thing(Thing * x) // callee accepts pointer
{
*x = stuff; // callee derefences ("*")
}
int main()
{
Thing y;
mutate_thing(&y); // caller takes address-of ("&")
}
In your case, the Thing is void *:
void f(void ** pv)
{
*pv = malloc(12); // or whatever
}
int main()
{
void * a1;
f(&a1);
}
Based on Kerrek SB's example I came with this to demonstrate void pointer-to-pointer as an argument and how it may be used.
#include <stdio.h>
void test(void ** jeez)
{
*jeez = (void *) (int) 3;
}
int main (int argc, char* argv[])
{
void *a;
test(&a);
int b = *(int *)&a;
printf("value returned = %d\n", b);
return 0;
}
Related
I noticed that my pointer address is different when it is passed to a function. U am not sure to access the value that exists inside the function? Please don't suggest returning the pointer value from the function. I strictly want to use void function.
output:
&nPtr = 6422300
&Ptr = 6422272
&nPtr = 6422300
See the below code:
#include<stdio.h>
void myFunc(int *Ptr){
printf("&Ptr = %d\n", &Ptr);
};
void main(){
int *nPtr;
printf("&nPtr = %d\n", &nPtr);
myFunc(nPtr);
printf("&nPtr = %d\n", &nPtr);
}
Let me be more clear. Here is the code that I am trying to fix. All what I want is to make the two pointers point to the same address. I want to use the best coding practice.
#include<stdlib.h>
#include<stdio.h>
void myFunc(int *Ptr){
Ptr = malloc(10*sizeof(int));
printf("*Ptr = %d\n", *Ptr);
};
void main(){
int *nPtr;
printf("*nPtr = %d\n", *nPtr);
myFunc(nPtr);
printf("*nPtr = %d\n", *nPtr);
}
In main(), you're getting the address of nPtr in main()'s stack frame; in myFunc(), you're getting the address of the copy of nPtr that is being passed by value to myFunc() as Ptr (so you're actually getting the address of Ptr, which is distinct) and exists on myFunc()'s stack frame.
nPtr and Ptr are separate variables in separate functions, and as such each must necessarily have a different address, i.e. &nPtr == &Ptr will always be false.
But you asked about nPtr == Ptr, i.e. can they contain the same value, and as pointers they can both contain the same pointer value. For example:
#include<stdio.h>
void myFunc(int *Ptr){
printf("Ptr = %p\n", (void *)Ptr);
};
int main(){
int x;
int *nPtr = &x;
printf("nPtr = %p\n", (void *)nPtr);
myFunc(nPtr);
printf("nPtr = %p\n", (void *)nPtr);
}
Output:
nPtr = 0x7ffe9a615104
Ptr = 0x7ffe9a615104
nPtr = 0x7ffe9a615104
For this function
void myFunc(int *Ptr){
printf("&Ptr = %d\n", &Ptr);
};
when you call it, although you are passing a pointer (which is for pointing to an integer) to this function , the system is creating a copy of the pointer and of course they will be at different memory address.
Hence when you return back to the main and retrieve your original pointer address, it will be displaying back the original address
below clang code run in ubuntu 18.04.2 LTS
I expect to output ptr3=123 the same as var ptr2,
But the result is ptr3=(null). How to modify the code that the result as I want?
#include <stdio.h>
void ptr_copy(char* d, char* s)
{
d = s;
}
int main(){
char *ptr = "123";
char* ptr2;
char* ptr3;
ptr2 = ptr;
ptr_copy(ptr3, ptr);
printf("ptr2=%s\n", ptr2);
printf("ptr3=%s\n", ptr3);
// output
// ptr2=123
// ptr3=(null)
}
Lets take a look at your "copy" function:
void ptr_copy(char* d, char* s)
{
d = s;
}
In the function the variable d is a local variable. The assignment to it will be lost once the function returns and d goes out of scope and ends its life.
That leaves you with an uninitialized ptr3 variable in the main function, and using it will lead to undefined behavior-
If you want to copy the pointer, you need to emulate pass by reference by passing a pointer to the pointer itself:
void ptr_copy(char** d, char* s)
{
*d = s;
}
and call it as
ptr_copy(&ptr3, ptr);
what you need is a different ptr_copy function, something like this:
void ptr_copy(char** dst, char* src) {
(*dst) = src;
}
ptr_copy(&ptr3, ptr);
the idea is that you fill the content of ptr to the place where ptr3 is stored (hence &ptr3, not ptr3).
When you pass a pointer to a function, the value of that pointer is passed (that is an address a given pointer points to). Thus pointer d within ptr_copy is a different pointer than ptr3 (it has a same value as ptr3 but it resides in another part of the memory). That's why the assignment d = s, change an address d points to, but it doesn't do anything with ptr3.
Indeed consider a function
void value_copy(int d, int s) {
d = s;
}
int i1 = 3;
int i3 = 2;
value_copy(i3, i1);
You don't expect i3 to be equal to 3 after the call of value_copy(), do you?
I am attempting to retrieve a pointer via a function in c. If the pointer is a return value from the function then it works. But if I pass the address of the pointer to the function, I can't update the dereferenced pointer value (which should be the address stored in the pointer) from within the function.
Please see the code and the output. Why don't I get the same results with both GetPointer1() and GetPointer2()? What am I missing?
#include <stdio.h>
#include <stdint.h>
uint8_t SrcArray[2][3] = {{11,12,13},{21,22,23}};
uint8_t *p1;
uint8_t *p2;
void GetPointer1(uint8_t *p);
uint8_t* GetPointer2(void);
int main()
{
printf ("&SrcArray[0][0]: %d\n", &SrcArray[0][0]);
GetPointer1(p1);
p2 = GetPointer2();
printf ("p1: %d\n",p1);
printf ("p2: %d\n",p2);
return 0;
}
void GetPointer1(uint8_t *p)
{
p = &SrcArray[0][0];
}
uint8_t* GetPointer2(void)
{
return &SrcArray[0][0];
}
Output:
&SrcArray[0][0]: 6295604
p1: 0
p2: 6295604
That is because the pointer you have in the function signature of GetPointer1(uint8_t *p) is passed by value. If you want to modify the pointer itself, you have to pass a pointer to a pointer:
void GetPointer1(uint8_t **p) {
*p = &SrcArray[0][0];
}
Otherwise, you may modify the piece memory to which the pointer points, but not the pointer itself.
Its is local to function GetPointer1 because it is a local variable which is passed as an value not as an address.
Here is the output details of your code for better understanding
inside main: &SrcArray[0][0]: 6295616
value of pointer p1: 0
address of pointer p1: 6295640
inside GetPointer1: 0
value of pointer p: 0 //which ur taking to a pointer p and modifying p whihc is local to that function.
address of pointer p: 64030024
inside GetPointer1 after assignment:value of pointer p: 6295616
address of pointer p: 64030024
If you want to pass address you need to use & before the variable say &p1.
Also as mentioned in one of the answer by IGarFieldI you can use pointer to a pointer.
void GetPointer1(uint8_t **p) {
*p = &SrcArray[0][0];
}
One more point since P1 is global variable, its accessible to all the functions you can directly use P1=SrcArray; which is allowed and does the same task.
ScrArray is equivalent &ScrArray[][] both gives the address of the array.
You have a variable p1 that is pointing to something. Then you pass it to a function GetPointer1. What happens there is that the value of the variable p1 (this is the address of the value it is pointing to!!!) is copied (!) to the function stack. This means that you can modify the pointed value (*p1), but not the original pointer (p1) itself, as you only have a copy of it. If you want to be able to modify the original pointer, then you have to retrieve the address of the pointer and pass this one to the function, i. e. you need a pointer to the pointer. You get this via the address-of operator &. So you need this:
getPointer1(uint8_t** p) { *p = /*...*/; }
and call it via
getPointer1(&p1);
#include <stdio.h>
#include <stdint.h>
int SrcArray[2][3] = {{11,12,13},{21,22,23}};
int *p1;
int *p2;
void GetPointer1(int **p);
int* GetPointer2(void);
int main()
{
printf ("&SrcArray[0][0]: %d\n", SrcArray[0][0]);
GetPointer1(&p1); /*<-- passing the reference of pointer p1 */
p2 = GetPointer2();
printf ("p1: %d\n",*p1);
printf ("p2: %d\n",*p2);
return 0;
}
void GetPointer1(int **p) /*<-- using double pointer */
{
*p = &SrcArray[0][0];
}
int* GetPointer2(void)
{
return &SrcArray[0][0];
}
o/p
rabi#rabi-VirtualBox:~/rabi/c$ gcc -g stack3.c
rabi#rabi-VirtualBox:~/rabi/c$ ./a.out
&SrcArray[0][0]: 11
p1: 11
p2: 11
rabi#rabi-VirtualBox:~/rabi/c$
" But if I pass the address of the pointer to the function." But you're not passing the address of the pointer, you're passing a copy of the pointer; changing the copy (as you noticed), doesn't change the original. If you actually pass in the &p (address of p) like you intended, you will be able to modify it - I'm unsure of syntax. edit: void GetPointer1(uint8_t **p) maybe?
This question already has an answer here:
C actions and variables
(1 answer)
Closed 7 years ago.
I have a function f1 which expects void pointer. From the caller I want to have generic logic of passing void pointer to A which modifies the pointer internally.
sample code is pasted below :
#include "stdio.h"
#include "malloc.h"
void f1(void* a)
{
printf("f(a) address = %p \n",a);
a = (void*)(int*)malloc(sizeof(int));
printf("a address = %p \n",a);
*(int*)a = 3;
printf("data = %d\n",*(int*)a);
}
void f(void)
{
void* a1=NULL;
printf("a1 address = %p \n",a1);
f1(a1);
printf("a1 address = %p \n",a1);
printf("Data.a1 = %d\n",*(int*)a1);
}
int main()
{
f();
}
But it causes segmentation fault. Is there any way to make it work without changing prototype of function f1?
C uses pass-by-value for function argument passing. If you have to change the passed variable itself from inside the function, you need to have a pointer to the variable.
In your case, it should be a pointer to pointer.
Otherwise, after the call to f1(a1);, in f(), a is still NULL and dereferencing it invokes undefined behaviour. Segmentation fault is one of the side effects of UB.
That said,
Please see why not to cast the return value of malloc() and family in C.
you don't need #include "malloc.h" to use malloc(), rather use #include <stdlib.h>. It is declared in stdlib.h header file.
You need to modify the pointer, not the ponted to data. So you must pass a pointer to the pointer, like this
void f1(void **a)
{
int *b;
b = malloc(sizeof(*b));
printf("b address = %p \n", b);
if (b != NULL)
{
b[0] = 3;
printf("data = %d\n", *(int *) b);
}
*a = b;
}
The way you do it, the pointer inside f1 is a copy of the passed pointer, they both contain the same initial value NULL, the value you used in f() to initialize a1, but you alter the value of the local pointer only.
You then dereference a1 which is still NULL, and dereferencing a NULL pointer, causes undefined behavior. In your case the behavior is that a segmentation fault happens.
In the following code p is pointer to an int. It is quite clear that p points to the address of i. Through my research i know &p points to the address of pointer p. But i don't get why would you need separate address for that. And also when would you use &p.
int main() {
int i = 3, *p = &i;
printf("%p",&p);
printf("%p",p);
return 0;
}
If p is pointer to int then
int **q = &p;
When you want to use pointer to pointer, then use the address of a single pointer to assign it to pointer to pointer.
Just to make a point that pointer is also a data-type and it stored in the memory location and it holds a valid memory location as its value. The address in which this valid memory location is stored is given by &p
Your printf() also needs to be fixed. %p expects void *
printf("%p",(void *)p);
But i don't get why would you need separate address for that
You don't, but there exists the address of operator so you can take the address of a pointer, which is what
printf("%p\n", &p);
is printing.
And also when would you use &p
There are cases where this might be useful, consider for example that you need to pass a pointer to a function which could be reassigned into the function, you can do something like this
int allocateIntegerArray(int **pointerToPointer, size_t someSize)
{
if (pointerToPointer == NULL)
return 0;
*pointerToPointer = malloc(someSize * sizeof(int));
return (*pointerToPointer != NULL);
}
then you could use this funciton the following way
int *pointer;
if (allocateIntergerArray(&pointer, 10) == 0)
{
fprintf(stderr, "Error, cannot allocate integer array\n");
/* do some extra cleanup or recover from this error, or exit() */
exit(0);
}
The pointers themselves are also variables and as such they need to be sotred somewhere, so the address of a pointer tells you where is the pointer stored, it's value tells you where it is pointing to.
By knowing where it is stored you can do things like the one explained above.
A trivial example:
int nochange(int *c, int *val)
{
c = val; // Changes local pointer c to point to val
// Note that C passes copies of the arguments, not actual references.
}
int do_change(int **c, int *val)
{
*c = val; // Accesses the real pointer c at its real location and makes
// that one point to val
// Even though c is a pointer-to-pointer copy, its value is
// copied too, and the value is the address of the real c
}
int main()
{
int a = 1;
int b = 2;
int *c = &a; // A pointer is also a datatype that resides in memory
printf("%d\n", *c); // Will print 1
nochange(c, &b);
printf("%d\n", *c); // Will print 1
do_change(&c, &b);
printf("%d\n", *c); // Will print 2 because c now points to b
}
I have a similar answer with a bit more detail here about pointer vs pointer-to-pointer: pointer of a pointer in linked list append