This question already has answers here:
Passing char pointer in C
(5 answers)
Closed 6 years ago.
I'm trying to understand the difference between pass by value and pass by reference, and I thought that I finally understand it, until I saw this code :
void change(char *p1)
{
p1="new";
}
int main()
{
char *txt1=(char*)malloc(200*sizeof(char));
txt1="original";
printf("before :%s\n",txt1);
change(txt1);
printf("after :%s\n",txt1);
}
Isn't it passing an address ? and then changing it and making it point to somewhere else ?
The output is :
before : original
after : original
Why is that?
There is no pass-by-reference in C. Function parameters are passed using pass-by-value. That is, p1 itself is passed by value. You can change the content of the memory address pointed to by p1 (*p1) from the called function, not p1 itself.
To clarify, for changing the content of a variable var, you need to pass the address of var, so, if you want to change a pointer itself, you need to pass the address of the pointer to the function.
That said, please see this discussion on why not to cast the return value of malloc() and family in C.
This is passing an address as value. To have the callee modify caller's local variable, pass address of what should be modified.
#include <stdio.h>
void change(char **p1)
{
*p1="new";
}
int main(void)
{
char *txt1; /* no causing memory leak */
txt1="original";
printf("before :%s\n",txt1);
change(&txt1);
printf("after :%s\n",txt1);
}
Pass By Reference and Pass By value.
Here's an example I've used before. Assume the following two functions:
void foo( T *p ) // where T is an arbitrary data type
{
*p = new_value(); // write new value to the thing p points to
}
void bar( void )
{
T var;
foo( &var ); // write new value to var
}
For function foo to update the contents of var (an object of type T) we must pass a pointer to var (type T *).
If we replace T with a pointer type P *, then the above code becomes
void foo( P **p )
{
*p = new_value(); // write new value to the thing p points to
}
void bar( void )
{
P *var;
foo( &var ); // write new value to var
}
The semantics are exactly the same; we want foo to write a new value to var, so we pass a pointer to var. It's just that in this case, var is already a pointer type, so we wind up passing a pointer to a pointer.
Basically, for foo to update the contents of var, you must pass the expression &var as the argument, meaning the type of the formal parameter p will always have one more level of indirection than the type of var.
Type of var Type of &var Type of p
----------- ------------ ---------
T T * T *
T * T ** T **
T ** T *** T ***
etc.
In function call change(txt1);, txt1 is passed by value. It is copied to the parameter p of function change. This makes pi points to the same string as txt1 pointing to. When new string is assigned to p1 then p1 changes to point to that string while txt1 pointing previous one.
this case is very similar to
char *s1 = "String";
char *s2 = s1; // Both s1 and s2 points to same string
s2 = "Another string" // Now s2 points to "Another string" while s1 pointing to "String".
Beside that your code is causing memory leak. It should be like
char *txt1=(char*)malloc(200*sizeof(char));
strcpy(txt1,"original");
Related
i want to ask a question about pointer:
void fun(const char** a) {...}
1.
const char* b = nullptr;
fun(&b);
2.
const char** b = nullptr;
fun(b);
why use 1 but not 2?
1 is good, 2 donnot work
C uses pass by value for function call arguments. That means a function receives a copy of the passed value, and there's no way for the function to directly change a variable in the caller.
For example, if you write
void set_to_5(int x)
{
x = 5;
}
and then write
int i = 3;
set_to_5(i);
printf("%d\n", i);
it prints 3, not 5. Or, if you write
void set_string(char *str)
{
str = "world";
}
and then write
char *p = "hello";
set_string(p);
printf("%s\n", p);
it prints hello, not world.
In both cases, the function successfully changes its copy of the passed value — x or str — but that doesn't have any effect on the variable in the caller (i or p).
When you want to have a function that does change a variable in its caller, one way to do that is to have the function accept a pointer. That looks like this:
void set_to_5_via_pointer(int *x)
{
*x = 5;
}
void set_string_via_pointer(char **str)
{
*str = "world";
}
Then you can write:
int i = 3;
set_to_5_via_pointer(&i);
printf("%d\n", i);
char *p = "hello";
set_string_via_pointer(&p);
printf("%s\n", p);
Now it does print 5 and world, as desired.
Notice that in each case I made three changes:
I added a * to the parameter type expected by the function (int x to int *x, char *str to char **str)
I added a * before each use of the parameter in the function, that is, where I actually set the new value (5 and "world")
I added a & before the variables where I passed them to the function (set_to_5_via_pointer(&i) and set_string_via_pointer(&p)).
One more thing. When you see a function declaration like
void set_string_via_pointer(char **str);
this does not necessarily mean that the right way to call the function is
char **x;
set_string_via_pointer(x);
Yes, here x is of type char **, and function set_string_via_pointer expects an argument of type char **, so it's a match. But if you declare and call
char *y;
set_string_via_pointer(&y);
that's also a perfectly good way to pass an argument of type char **, and in this case, it's certainly they way that was expected.
const char* b = nullptr;
fun(&b);
This passes the pointer b by reference — or emulates pass by reference semantics — i.e. the memory address of where the variable is stored is passed instead of its value. This allows you to access the pointer originally declared in the calling function, and any changes made to that pointer in the called function would be visible in the calling function.
const char** b = nullptr;
fun(b);
Au contraire, this passes b by value. If you change the pointer to point to some other memory location in the called function, that change will not be reflected back in the calling function. Any attempt to dereference it while it is pointing to NULL would result in undefined behaviour as per the following clauses of C11:
If an invalid value has been assigned to the pointer, the behavior of
the unary * operator is undefined.
[...]
Among the invalid values for dereferencing a pointer by the unary *
operator are a null pointer, [...]
[6.5.3.2 Address and indirection operators, C11]
why use 1 but not 2?
Why use either of them?
1 is good, 2 donnot work
“There is nothing either good or bad, but thinking makes it so.” — They both serve different purposes. Though, the purpose of the second snippet is rather ambiguous here.
This code snippet
void fun(const char** a) {...}
1.
const char* b = nullptr;
fun(&b);
means passing the pointer b to the function fun by reference in the C meaning. So dereferencing the pointer to pointer a within the function you can change the original pointer b passed to the function indirectly through a pointer to it.
Here is a demonstration program.
#include <stdio.h>
void fun( const char **a )
{
*a = "Hello World!";
}
int main( void )
{
const char *b = NULL;
fun( &b );
puts( b );
}
The program output is
Hello World!
As you can see the pointer b is passed to the function indirectly through a pointer to it (by reference in the C meaning). Thus dereferencing the pointer to pointer a
*a = "Hello World!";
you can change the original pointer b defined in main.
In the second case
2.
const char** b = nullptr;
fun(b);
the pointer b is passed by value and if the function fun will dereference the null pointer then undefined behavior will be invoked.
This question already has answers here:
How do I modify a pointer that has been passed into a function in C?
(7 answers)
Closed 1 year ago.
I have a question about pointer.
Recently, I was looking some system programming tutorial. The teacher is talking about asprintf() Function.
According to the man page, the definition of asprintf() is:
int asprintf(char **ret, const char *format, ...);
However, I found that the teacher tends to create a single pointer and then pass the address of that single pointer to the first parameter. Like this:
int main()
{
char *buffer;
int r;
r = asprintf(&buffer,"The total is %d\n",5+8);
puts(buffer);
printf("%d characters generated\n",r);
return(0);
}
I am wondering why don't we declare double pointer and then pass that double pointer to the function, just like the definition.
In addition, the teacher use the same tricks in other function too, such as: getline()
Therefore, is there any advantage that we would choose single pointer over double pointer, even the definition of the function is double pointer?
Thanks for everyone for replying in advanced. :))
asprintf will allocate some memory and write the printf result into that memory.
To get this resulting memory buffer, you pass a pointer to a local variable (in your case: buffer) as the first argument. This pointer is then dereferenced in the function, to change the value of your local variable, so the code in asprintf semantically does something like this:
int asprintf(char **ret, const char *format, ...) {
*ref = malloc(some_size);
sprintf(*ret, format, ...);
}
What would now happen if you didn't have a local variable of type char * and passed a pointer to this variable, but instead had a local variable of type char **, like you suggested:
char **buffer;
asprintf(buffer, "The total is %d\n", 5+8);
Well, asprintf would again just dereference this pointer you just passed. But in this code, it doesn't yet point to anything meaningful, so this would result in an error. We must have enough memory allocated at the address we are passing to asprintf so it can store a char* there for us.
Now, this would work:
char *buffer;
char **pointer_to_buffer = &buffer;
asprintf(pointer_to_buffer, "The total is %d\n", 5+8);
but it is just more complicated and verbose.
But why do we do this whole pointer-to-pointer thing? Well, you would certainly first try to simply pass the pointer, instead of a pointer-to-pointer, like this:
char *buffer;
asprintf(buffer, "The total is %d\n", 5+8);
with asprintf semantically doing something like this:
int asprintf(char *ret, const char *format, ...) {
ref = malloc(some_size);
sprintf(ret, format, ...);
}
However, it is critical that here, buffer is passed by value. This means that when asprintf locally modifies ret, it modifies a copy of the value of our buffer. We, the caller, will not be able to see this change in our variable buffer. This is why we pass a pointer-to our local variable buffer, not the value itself.
I am wondering why don't we declare double pointer and then pass that double pointer to the function, just like the definition.
Because you want to update the value stored in buffer. The type of the expression &buffer is char **.
Remember, in order for a function to write to any of its parameters, you must pass a pointer to that parameter:
void foo( T *ptr )
{
*ptr = new_T_value(); // writes a new value of type T to the thing ptr points to
}
void bar( void )
{
T var;
foo( &var ); // writes a new value to var
}
Thus, the following are true:
ptr == &var // T * == T *
*ptr == var // T == T
IOW, writing to the expression *ptr is the same as writing to var.
So, why not just create a pointer variable in bar and pass it to foo? If we wrote something like
void bar( void )
{
T *vptr;
foo( vptr );
}
the problem is that vptr doesn't point to anything meaningful - we have
ptr == vptr // T * == T *
*ptr == *vptr == ??? // T == T == ???
There's no object of type T for us to update. Now, we could create another object for vptr to point to:
void bar( void )
{
T var;
T *vptr = &var;
foo( vptr );
}
and that will work as expected, but the extra pointer variable is redundant in this case.
The same logic holds for pointer objects - let's replace T with a pointer type, P *. Then our code becomes:
void foo( P * *ptr ) // or P **ptr
{
*ptr = new_P_star_value(); // writes a new value of type P * to the thing ptr points to
}
void bar( void )
{
P * var; // or P *var
foo( &var ); // writes a new value to var
}
which gives us
ptr == &var
*ptr == var == some_P_star_value
**ptr == *var == *some_P_star_value == some_P_value
Same thing as above - we want to write a new value to var. To do that we pass a pointer to it, even though var is already a pointer type. This is why multiple indirection exists in the first place.
Most of the time when you see a function that has a pointer or pointer-to-pointer parameter, it's expecting you to pass the address of another object (obtained with the & operator), not a pointer variable as such.
If you want to change an object used as an argument in a function you need to pass it by reference.
In C passing by reference means passing an object indirectly through a pointer to it. Thus dereferencing the pointer a function can get a direct access to the original pointer.
Consider this demonstrative program and compare the result of calls of the two functions f and g.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void f( char *s )
{
s = malloc( 14 );
strcpy( s, "Hello World!" );
}
void g( char **ps )
{
*ps = malloc( 14 );
strcpy( *ps, "Hello World!" );
}
int main(void)
{
char *s = NULL;
f( s );
if ( s != NULL ) puts( s );
else puts( "s is a null pointer." );
g( &s );
if ( s != NULL ) puts( s );
else puts( "s is a null pointer." );
free( s );
return 0;
}
The program output is
s is a null pointer.
Hello World!
The function f accepts the pointer s declared in main by value. It means that the function deals with a copy of the value of the pointer s. Changing the copy does not affect the original pointer s. So the function produces a memory leak because it allocates dynamically a memory and the address of the allocated memory stored in the local variable (function parameter) s will be lost after exiting the function.
The function g accepts the pointer s by reference through a pointer to it. So dereferencing its parameter the function has a direct access to the original pointer s and can change it.
This question already has answers here:
Changing address contained by pointer using function
(5 answers)
Closed 2 years ago.
I'm new to C, sorry if my question sound dumb.
I see some function takes a "double" pointer as parameter, for example:
int main(int argc, char **argv)
{
...
}
I can understand the need for a double pointer such as argv, since argv is the pointer to the first element of argument array whose element is also a pointer to a char type. double pointer is needed in this case.
But for some functions like:
int getaddrinfo(const char *host, const char *service, const struct addrinfo *hints, struct addrinfo **result);
I don't understand why a double point is needed, since there is no array element involved, and I think getaddrinfo calls malloc internally, so it might be a reason to use double pointer, but we can have sth like this:
int main()
{
char *ptr_main;
test(ptr_main);
free(ptr_main);
}
void test(char *ptr)
{
ptr = malloc(10);
}
so the parameter is a single pointer char * ptr, no char **ptr is needed?
Passing a pointer, or address of an object allows the value stored at that location in memory to be changed by the function, so when the function returns, the information stored at that address now contains updated values. Likewise if a function argument accepts a pointer variable, and the pointer variable is to be changed, the address to that pointer must be passed, thus requiring the function prototype to be a pointer-to-pointer.
Addressing your question may illustrate: getaddrinfo question: I don't understand why a double point is needed, since there is no array element involved
Usage for this struct is typically:
struct addrinfo *result;//pointer variable
getaddrinfo("hostname", "servicename", NULL, &result);
// |_Passing address of a pointer variable.
// thus requiring prototype to accommodate
So as explained, for the function to receive updated struct information, it needs to send the address of the pointer variable, requiring it to be a double pointer:
int getaddrinfo(const char *host, ..., struct addrinfo **result);
Your code is incorrect. ptr is local to the scope of test. A pointer is just a number representing a memory address. You probably wouldn't expect test in the following code to affect the value of number_main, right?
int main()
{
int number_main;
test(number_main);
printf("%d\n", number_main);
}
void test(int number_main)
{
number_main = 10;
}
Maybe it helps if you internalize char * as some fictional type you'll call number_that_represents_memory_address, which you then think about as no different than int in this case?
This function
void test(char *ptr)
{
ptr = malloc(10);
}
that shall be declared before its usage in main deals with a copy of the value of the passed argument in main
char *ptr_main;
test(ptr_main);
You can imagine the function call and the function definition the following way
char *ptr_main;
test(ptr_main);
//...
void test( /* char *ptr */ )
{
char *ptr = ptr_main;
ptr = malloc(10);
}
So as you can see within the function it is the local variable ptr that is changed. The argument ptr_main that was not initialized in main and has indeterminate value stays unchanged.
To change the original pointer ptr_main you have to pass it to the function by reference.
In C the mechanism of passing by reference is implemented by passing an object indirectly through a pointer to it.
From the C Standard (6.2.5 Types)
— A pointer type may be derived from a function type or an object
type, called the referenced type. A pointer type describes an object
whose value provides a reference to an entity of the referenced
type. A pointer type derived from the referenced type T is sometimes
called ‘‘pointer to T’’. The construction of a pointer type from a
referenced type is called ‘‘pointer type derivation’’. A pointer type
is a complete object type.
So the function definition should look like
void test( char **ptr )
{
*ptr = malloc(10);
}
And called like
test( &ptr_main );
Thus dereferencing the pointer ptr in the function we get a direct access to the pointed object (pointer) ptr_main and it is the pointed (referenced) object that is changed now in the function
To make it more clear consider the following demonstrative program.
#include <stdio.h>
#include <stdlib.h>
void f1( int *px )
{
*px = 10;
}
void f2( int **ppx )
{
*ppx = malloc( sizeof( int ) );
**ppx = 20;
}
int main(void)
{
int x = 0;
printf( "Before calling f1 x = %d\n", x );
f1( &x );
printf( "After calling f1 x = %d\n", x );
int *px = &x;
printf( "Before calling f2 px = %p and *px = %d\n", ( void * )px, *px );
f2( &px );
printf( "After calling f2 px = %p and *px = %d\n", ( void * )px, *px );
free( px );
return 0;
}
The program output might look like
Before calling f1 x = 0
After calling f1 x = 10
Before calling f2 px = 0x7ffe79dd572c and *px = 10
After calling f2 px = 0x55db88f5d270 and *px = 20
To change the object x declared in main in the function f1 we need to pass it to the function by reference. Otherwise the function will deal with a copy of the value of the object.
The same situation takes place with the pointer px. Pointers are objects. If we want to change the pointer px declared in main in the function f2 we need to pass it to the function by reference. Otherwise the function will deal with a copy of the value of the object.
And as you can see from the program output the function f2 indeed changed the value of the pointer px declared in main.
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?
Hello I am a beginner in C programming language. Recently I read about call by value and call by address. I have learned that in call by address changes in the called functions reflects the callee. However the following code does not work like that.
int x = 10,y = 20;
void change_by_add(int *ptr) {
ptr = &y;
printf("\n Inside change_by_add\t %d",*ptr);
// here *ptr is printing 20
}
void main(){
int *p;
p = &x;
change_by_add(p);
printf("\nInside main\t %d", *p);
// here *p is still pointing to address of x and printing 10
}
When I am passing address then why the changes made by called function does not reflect caller?
The function is assigning a new address to the pointer but the pointer itself is being passed by value, as all arguments are in C. To change the value of a pointer variable the address of the pointer itself must be passed:
void change_by_add(int **ptr)
{
*ptr = &y;
}
change_by_add(&p);
See C FAQ Question 4.8.
Passing by reference does not exist in C but can be achieved by passing the address of the variable who's value is to be changed to a function. For example:
void add_to_int(int* a_value, int a_increment)
{
*a_value += a_increment;
}
You are simply setting the value of the pointer in the function, not the value of the pointed to variable. The function should use the following code:
*ptr = y;
This derefences the pointer (exposing the value pointed to), and therefore when you use the equals operator, the memory pointed at is modified, not the pointer itself. I hope this helps to clarify things.
Changes made by called function does not get reflected by the caller because you are overriding the pointer address in the called function i.e ptr = &y;.
Initially, you passed the address of x but you are changing it with the address of y.
If you really want to implement the concept of call by address then change value instead of address.
Example:
void change_by_add(int *ptr) {
*ptr = y; //changing value
printf("\nInside change_by_add\t %d",*ptr);
}
void main(){
int *p;
p = &x;
change_by_add(p);
printf("\nInside main\t %d \n", *p);
return 0;
}
Output
Inside change_by_add 20
Inside main 20
There is no such thing as call by address in C. There is only call by value. What one does when a function needs to modify an argument in a way that is visible to the caller is to have the caller pass a pointer to something, and have the called function write the update though that pointer. Note that the pointer itself is still sent as call-by-value - that is: the called function gets its own copy of the pointer and could change it to point to anything else if it wants to.