I have this function signature:
void myFunction(int *const ptr);
What's the point of the const keyword in this particular context?
Even if ptr wasn't a const variable, I couldn't modify to what address it points to, because it's passed by value, so if I had another function like this:
void myAnotherFunction(int *ptr);
And inside its implementation did something like this:
//...
ptr = malloc(1023);
//...
This wouldn't affect the passed value (outside this function, of course).
So the question is: what's the point of using myFunction() signature instead of myAnotherFunction() one? (beside that you get a compile-time error).
ptr = malloc(1023);
This wound't affect the passed value (outside this function, of
course).
To sum up. Indeed that way original pointer would not be affected (it would still point to same object because ptr is copy of the original pointer), but you can still make that pointer point to a different object inside myAnotherFunction and change value of that object through that pointer. e.g. in myAnotherFunction you could do:
ptr = &y;
*ptr = 9;
Whereas in the first case when you have a constant pointer, you can't assign a new address to it, but you can still change the value of object to which it points using dereferencing. A constant pointer means you can't assign a new address to it, pointer to a constant object means you can't change value of object to which it points, but you can assign new address to the pointer.
It might make more sense if you consider that the function
void myFunction(int *const ptr);
might be manipulating many pointers, and assigning them and reassigning them, and an invariant of the algorithm it is executing is that the input pointer should never be changed. Then, labeling it const might be very helpful, or at least make you feel more confident that its been implemented correctly.
Related
Is passing pointer argument, pass by value in C++? Since i see that any change to the pointer as such is not reflected outside the method. The changes i do by dereferencing the pointer is reflected though.
In that case, is it acceptable/standard procedure to use pointer to pointer as argument to a function to modify the pointer value as such within a function?
Yes to both.
Pointers are passed by value as anything else. That means the contents of the pointer variable (the address of the object pointed to) is copied. That means that if you change the value of the pointer in the function body, that change will not be reflected in the external pointer that will still point to the old object. But you can change the value of the object pointed to.
If you want to reflect changes made to the pointer to the external pointer (make it point to something else), you need two levels of indirection (pointer to pointer). When calling functions it's done by putting a & before the name of the pointer. It is the standard C way of doing things.
When using C++, using references is preferred to pointer (henceforth also to pointer to pointer).
For the why references should be preferred to pointers, there is several reasons:
references introduce less syntaxic noise than pointers in function body
references keep more informations than pointers, than can be useful for compiler
Drawbacks of references are mostly:
they break the simple pass-by-value rule of C, what makes understanding the behavior of a function regarding of parameters (will they be changed ?) less obvious. You also need function prototype to be sure. But that is not really worse than the multiple pointer levels necessary when using C.
they are not supported by C, that can be a problem when you write code that should work with both C and C++ programs (but that's not the most usual case).
In the specific case of pointer to pointer, the difference is mostly simplicity, but using reference it may also be easy to remove both levels of pointers and pass only one reference instead of a pointer to pointer.
I understand the confusion here. The concepts of "pass by value" and "pass by reference" are not so clear even if they seem to be so.
Bear in mind that the computer does not know these concepts and does not behave according to it.
The computer does not know about the types. Hence it does not make a distinction of pointers and values.
Let me try to explain by and example:
void func1(int x) //copy some value to local variable x (of type int)
{
x = 5; //modify local variable. lost after function call
}
void func2(int *x) //copy some value to local variable x (of type int*)
{
int a;
x = &a; //modify local variable. lost after function call.
}
void func3(int *x) //copy some value to local variable x(of type int*)
{
*x = 10; //x is local but *x is not! change is saved after function call!
}
func1 and func2 are identical. Both modify a local variable. Modification is lost after function is popped off the stack.
func3 has ability to change another memory location (a variable which is not local to the function).
basically, every function call is "call by value". But in the case of a pointer type, we have a way to change the content of a remote address in memory.
Pass by value using Pointers
I'll explain it by example:
void f(int *ptr)
{
cout<<*ptr;
}
int main ()
{
int a=10;
int *aptr=&a;
f(aptr);
return 0;
}
Here, in main function a is an integer variable whose content is 10 and address is 00F8FB04 (assume).
aptr is pointer to integer, that store the address of integer variable a, so aptr content is address of integer variable a that is 00F8FB04. When we pass aptr as the function argument only content of aptr (that is address) are copies to function parameter.
So, ptr will receive the copy of content of aptr (that is address 00F8FB04)
Either a pointer to a pointer, or a reference to a pointer, is what you would use if you wanted to potentially change the pointer itself. To your original question, technically, yes, all parameters are passed by value.
Yes it is, as it is in C.
In that case, is it acceptable/standard procedure to use pointer to pointer as argument to a function to modify the pointer value as such within a function?
In which case? What do you want? You can use real references with the & modifier.
void func(type &ref);
I'm learning how to program for ALSA in Linux and there's a piece of code like this:
snd_pcm_t * _soundDevice;
bool Init(const char *name)
{
int i;
int err;
snd_pcm_hw_params_t *hw_params;
if( name == NULL )
{
// Try to open the default device
err = snd_pcm_open( &_soundDevice, "plughw:0,0", SND_PCM_STREAM_PLAYBACK, 0 );
}
As you can see, it first creates the pointer to the struct snd_pmc_t and name it _soundDevice. Other parts of the code, however, use only the first pointer:
if ((err = snd_pcm_hw_params_any (_soundDevice, hw_params)) < 0)
I understand that a pointer to a struct is helpful to pass as an argument because passing the entire struct as a copy would be bad, and I also understand that this function modifies the content of the struct that the pointer points to, but why should somebody need a pointer to a pointer to a struct?
why should somebody need a pointer to a pointer to a struct?
This most often shows up when you need to pass a pointer into a function in a way that allows the function to change what that pointer points to. One idiomatic C way is to pass the pointer by pointer, resulting in that second level of indirection you're wondering about.
In your example snd_pcm_open modifies its first argument (i.e. makes _soundDevice point someplace new), whereas snd_pcm_hw_params_any doesn't.
If snd_pcm_open were to take snd_pcm_t* rather than snd_pcm_t**, it wouldn't be able to repoint the first argument in a manner that would propagate back to the caller.
In C, parameter passing is by value (or by copy if you prefer), so if you want a function to modify the passed argument in return you need to pass its address.
Having a pointer to a pointer allows the function to modify your local pointer. If you passed just a regular pointer, the function gets that pointer on the stack. If it modifies that value (of the pointer, not the pointed-to data), the value is lost when the function returns the same way that changes to an int passed to a function would be lost. If you instead pass a pointer to a pointer, it can modify your pointer, which will still exist after the function returns.
If, for instance, the function is allocating memory for that structure, it can set your pointer to the address of the newly allocated memory or NULL if the allocation fails. In this case, it looks like this is being used as a second return value. It wants to return an error code as the actual return value and a pointer as a second value.
Some times the target is not to change an object, but to change the pointer that points to it.
Imagine a function 'A' that choses among several functions
int A(someType* funcChosen)
{
funcChosen = ...; //a pointer to a function
}
someType* myFunc;
int res = A(myFunc);
will modify myFunc. But you want a pointer to that function, not the code (??) of it. So better:
int A(someType** funChosen);
someType* myFunc;
int res = A(&myFunc);
This question already has answers here:
change pointer passed by value
(6 answers)
Closed 7 years ago.
I had a programming assignment a while back where I stumbled upon this little problem: when I gave a function a pointer as a parameter, I could not change the address it pointed at. I solved that by returning the new adress I wanted the pointer to point to. But I am still wondering why it's not possible to manipulate a pointer parameter because all memory allocating functions work with a return value as well instead of a parameter list.
Was I possibly doing something wrong? Or is it really not possible to change the pointee? Does anyone have an explanation?
Example:
void foo(int *ptr)
{
ptr=malloc(sizeof(int));
} /* after calling this function I would
expect the pointee to have changed to the
newly allocate memory but it stays NULL*/
int main()
{
int *ptr=NULL;
foo(ptr);
return 0;
}
It's because all parameters are passed by value in C. If you call a function with a pointer parameter you may change that pointer in the function but this will have no effect on the caller's value of the pointer.
If you need to communicate a modified pointer back to the caller, returning the modified pointer is the way to go. Note that this also only passes a value back.
Another way would be to pass the address of a pointer (i.e. a pointer to a pointer). The called function can then store a new pointer value at the given address.
Memory allocating functions return the pointer value, so it is generally
assigned to a pointer.
Passing a pointer to a function as an argument is a different story,
because changing it won't change the original (pass by value). That's
why we use pointers in these cases, to give the address of a variable
and change its value in the function.
If you need to pass a pointer instead, and change what it points to, use
a pointer to a pointer!
void
my_function(int **pointer)
{
*pointer = &something; // will change the pointer address
}
int *my_pointer = &something_else;
my_function(&my_pointer);
I declare a variable (of type TEST containing a static array) and call several functions passing a pointer to this variable.
typedef struct
{
char data[50];
} TEST;
int main(int argc,char *argv[])
{
TEST *ptr = malloc(sizeof(TEST));
func_one(ptr);
printf("data: %s\n", ptr->data);
}
void func_one(TEST *ptr)
{
func_two(ptr);
}
void func_two(TEST *ptr)
{
strcpy(ptr->data, "hello");
}
Will the above print statement print "hello"? My program currently prints "hello", but I am confused because from my understanding, I know that ptr is being passed by value, rather than by reference.
You're right, the pointer is passed by value, so the pointer ptr in the main function is copied to the ptr variable in func_one, and it is in turn copied to the ptr variable in func_two.
You are, however, not trying to modify the pointer, but the data it points to, so it's the data is passed by reference, but the pointer to the data is not.
Though technically C doesn't have "pass by reference", it can only be emulated by using pointers.
Also, you would have the same outcome it you didn't allocate the data on the heap, and used the address-of operator:
TEST data;
func_one(&test);
The pointer is being passed by value, that is correct. That means that the array that is being pointed to is passed by reference.
(I have a feeling that in the purest Computer Science sense that may be incorrect but it is close enough for all practical purposes).
Pass-by-reference means you're passing a reference to some data. Pass-by-value means you're passing a copy of some data.
In this case, you're passing a pointer by value. But what's a pointer? It's a reference to some data.
You're passing the pointer itself by value, but given that it's a pointer, the side effect is that any data it points to is essentially passed by reference.
If I had a function defined arbitrarily like:
char* myfunction(int, int[]);
which, as shown, returns a character pointer. Do you have to write in the calling function something like:
char *ptr = myfunction( ... );
Or is there a way to use the pointer that is returned by the function without creating another pointer to the one returned?
I ask because, given how I described above, you essentially have a pointer returned, and another pointer assigned to that one. Thus, you then have an unused pointer (the one returned by the function) taking up memory.
If there is no way to explicitly use the pointer that is returned, is there a way to assign a new pointer to the returned pointer and free the unused one?
A pointer is a really small thing. It's just a representation of the address of an object. You shouldn't be concerned about creating extra copies of a pointer (it's like creating an extra int).
char* foo() {
char* bar;
// some stuff that mallocs a value and assigns to bar
return bar;
}
char* x = foo();
In the simplified example above, the bar pointer is created on the stack, and the code in the comments points it at some memory in the heap (with a Malloc or something). When the function foo() is evaluated, the value of the pointer (e.g. The address of the memory) is popped off the stack and assigned to x. There is no unused pointer hanging around, it's just been reassigned. The memory that it points to remains exactly where it is and isn't duplicated.
You aren't creating extra copies of the memory that the pointer is pointing to. In fact, that's a large reason to pref pointers, because it involves copying less.
The pointer that is returned by the function doesn't waste memory as you state. When the function returns, and as soon as the affectation ptr = myfunction(...); is done, the returned value doesn't exist anymore in memory.
But to answer your question, yes you can use the returned pointer directly, without a temporary variable. Although it is a rvalue (you can't do myfunction() = NULL for example), the location it's pointing to is at your disposal : *myfunction() = 3 is valid, granted the pointer returned is valid.
I prefer using a temporary variable, as you can reuse the value in 2 or more expressions, and it is far more readable in my opinion.