8

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?

3
  • 4
    Look up "pass by value". Commented Sep 16, 2012 at 17:21
  • Because you pass it by value. Commented Sep 16, 2012 at 17:21
  • 2
    c-faq.com/ptrs/passptrinit.html Commented Sep 16, 2012 at 17:22

4 Answers 4

10

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); 
Sign up to request clarification or add additional context in comments.

2 Comments

In C, you can do that with void f(void **a).
@chris Good point. Brain fart moment.
10

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)); // ... 

Comments

5

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); } 

Comments

1

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; } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.