Return address of pointer through function - c++

#include<iostream>
using namespace std;
int teradata=65;
int &pointer(int *p2)
{
p2=&teradata;
return &p2;
}
int main()
{
int a=10;
int *p=&a;
int **p3;
p3=pointer(p);
cout<<p3;
return 0;
}
Actually I am trying to return the address of pointer p2 and store it in pointer p3 which is a pointer to a double. Please help correct this program and tell me the error which I did in this program.

Since a function parameter is basically an initialized local variable, returning its address is unproductive if the variable is an object. The object no longer exists when the function returns, so the address itself is also invalid.
If you actually want the address of the pointer variable that was passed to the function, the function needs to accept a reference to the pointer variable being passed. And, it needs to specify the correct return type, which is a pointer to a pointer.
int **pointer(int *&p2) {
p2=&teradata;
return &p2;
}
Your code should not have compiled, and your compiler should have issued a diagnostic about an invalid conversion.

The operation &p2 returns the address of p2. p2 is a pointer to int. So the function pointer should return int ** and not int &:
int **pointer(int *p2) {
p2=&teradata;
return &p2;
}

Related

Is function name an address to first instruction of that function in c?

Why is compiler saying that this is not pointer:
#include <stdio.h>
double f(){ return 1.2; }
int main(){
int i=0;
double d =f()[0]; //f() is not pointer? it should be
printf("%i\n",d);
}
error:
subscripted value is neither array nor pointer nor vector
double d =f()[0];
But is I have declared a function pointer, and then used a name of a function, then it will become pointer:
#include <stdio.h>
int op(int (*op)(int,int), int a, int b){ return op(a,b); }
int add(int a, int b){ return a+b; }
int main(){
printf("%i\n",op(add, 1, 2)); //here: add() will magically become pointer, different context
}
So in first case, I wanted to dereference the function, in hope, the name of the funtion is pointer (and so derefencing is permitted). In second example, the function pointer is declared with pointer, so the function add will decay to pointer (compare to printf("%i\n",op(&add,1,2))) will also work. So why is problem with the first one?
For a function f, or callable in general, f() is calling the function and evaluates to the type declared as the functions return type. Functions can decay to pointer to function, similar to arrays, but when you call the function, this doesn't happen:
int foo(int,int){ return 1;}
int main() {
using fptr = int (*)(int,int);
fptr p = foo; // <- function pointer (note: no & needed because it decays to function pointer)
fptr q = &foo; // <- also function pointer
int x = foo(1,2); // <- function call
}
In your examples:
double d =f()[0]; //f() is not pointer? it should be
No, f() is not a pointer. f returns a double.
printf("%i\n",op(add, 1, 2)); //here: add() will magically become pointer, different context
No. add() will not magically become a pointer. add is the function that will automagically decay to function pointer (acutally it isnt that "magic").

C++ Call by reference

If I have a function which takes a pointer to an integer, and I pass a reference to an integer variable from my main, is this call by value or call by reference? Sample code:
#include <iostream>
using namespace std;
void fun(int *a){
//Code block
}
int main(){
int a = 5;
fun(&a);
return 0;
}
In the above code, is the call to function fun a call by value or call by reference?
Your call is a pass by value, but of type int* not of argument type int. This means that a copy of the pointer is made and passed to the function. You can change the value of what it points to but not of the pointer.
So if your function is like this
void fun(int *a)
{
*a = 10;
}
and you call from main like this
int main() {
int b = 1;
fun(&b);
// now b = 10;
return 0;
}
you could modify the value of b by passing a pointer to it to your function.
The same effect would be if you did the following - which is passing by reference
void fun2(int& a)
{
a = 5;
}
int main()
{
int b = 10;
fun2(b);
// now b = 5;
return 0;
}
Now consider a third function that takes an integer argument by value
void fun3(int a)
{
a = 10;
}
int main()
{
int b = 1;
fun3(b);
// b is still 1 now!
return 0;
}
With pass by value, fun3 changes the copy of the argument passed to it, not the variable b in the scope of main.
Passing by (non-const) reference or pointer allows the modification of the argument that is passed to it. Passing by value or const reference will not allow the argument passed to it to be changed.
You're passing a pointer to a, by value.
Depending on which level of abstraction you are speaking, you could say that you are therefore passing a by pointer, or passing a by "handle". In broader terms, "passing a by reference" would not be strictly incorrect, but it is incorrect in C++ because "reference" means something specific in C++. You have no C++ references in this code.
You are passing by value the address where a is located.
So when in your void called fun you type *a, you're accessing the value of a.
But as I've said, you're passing by value an int pointer to a.
It is call by reference as you are passing reference the address reference to your variable so,
inside function
*a = 100;
changes the value of a in caller function as the content at that address has been changed.
But address is passed by value so
a = NULL;
will not change a, as a still be pointing to same address.

Changing constant pointer's address

I'm trying to understand one thing.
I know I can't change constant pointer's value, but I can change its address, if I initialize a pointer the following way:
int foo = 3;
const int *ptr = &foo;
*ptr = 6; // throws an error
int bar = 0;
ptr = &bar; // foo == 0
Now, let's say I declare (/define, I never remember which one) a function:
void change(const int arr[], int size);
int main() {
int foo[2] = {};
change(foo, 2);
std::cout << foo[0];
}
void change(const int arr[], int size) {
// arr[0] = 5 - throws an error
int bar = 5;
arr = &bar;
}
The last line in the code above doesn't throw any errors. However, when the function is over and I display the first element, it shows 0 - so nothing has changed.
Why is that so?
In both situations I have constant pointers, and I try to change its address. In the first example it works. In the second one it doesn't.
I also have another question. I've been told that if I want to pass two-pointers type to the function, const keyword won't work as expected. Is that true? And if so, then what's the reason?
You're screwing up the terminology a lot, so I'm going to start there because I think it is a major cause of your confusion. Consider:
int x;
int* p = &x;
x is an int and p is a "pointer to int". To modify the value of p means to change p itself to point somewhere else. A pointers value is the address it holds. This pointer p holds an address of an int object. To change the pointer's value doesn't mean to change the int object. For example, p = 0; would be modifying p's value.
In addition to that, the address of p is not the address it holds. The address of p would be what you get if you did &p and would be of type "pointer to pointer to int". That is, the address of p is where you would find the pointer p in memory. Since an object doesn't move around in memory, there's no such thing as "changing its address".
So now that's out of the way, let's understand what a constant pointer is. const int* is not a constant pointer. It's a pointer to a constant object. The object it points to is constant, not the pointer itself. A constant pointer type would look more like int* const. Here the const applies to the pointer, so it is of type "const pointer to int".
Okay, now I'll quickly give you an easy way to remember the difference between declaration and definition. If you bought a dictionary and all it had was a list of words in it, would you really call it a dictionary? No, a dictionary is supposed to filled with definitions of words. It should tell you what those words mean. The dictionary with no definition is only declaring that such words exist in the given language. So a declaration says that something exists, and a definition gives the meaning of it. In your case:
// Declaration
void change(const int arr[], int size);
// Definition
void change(const int arr[], int size) {
// arr[0] = 5 - throws an error
int bar = 5;
arr = &bar;
}
Now to explain the issue here. There's no such thing as an array argument type. Any array type argument is converted to a pointer. So the declaration of change is actually identical to:
void change(const int arr*, int size);
when you do arr = &bar; you are simply assigning the address of bar to the pointer arr. That has no effect on the array elements that arr is pointing to. Why should it? You are simply changing where arr points to, not the objects it points at. And in fact you can't change the objects it points at because they are const ints.
I know I can't change constant pointer's value, but I can change its address
Nah. You can't change the address of anything. Did you mean that you can't change the object it points to, but you can change the pointer itself? Because that's what is the truth - in the case of a pointer-to-const type. However, if you have a const pointer to a non-const object, then you can't change the pointer, you can only change whatever it points to.
Addendum (edit): a handy rule of thumb is that const applies to what stands on its left side, except when nothing stands on its left side, because then it applies to the type that is on its right side. Examples:
const int *ptr;
int const *ptr; // these two are equivalent: non-const pointer to const int
int *const ptr; // const pointer to non-const int
int const *const ptr; // const pointer to const int
const int *const ptr; // same as above
However, when the function is over and I display the first element, it shows 0 - so nothing has changed.
Scope. arr is a function argument - so it's local to the function. Whatever you do with it, it won't be effective outside of the function. To achieve what you want, declare it as a reference:
void change(const int *&arr, int size)
I've been told that if I want to pass two-pointers type to the function, const keyword won't work as expected. Is that true?
This depends on what your expectations are. If you read the standard attentively and have proper expectations, then it will indeed work as expected. Examples:
const int **ptr; // pointer to pointer to const int
int const **ptr; // same as above
const int *const *ptr; // pointer to const pointer to const int
etc. You can generate more of these funky declarations using CDecl
The first thing is using the proper terms, which actually helps in understanding:
const int *ptr = &foo;
That is a pointer to a constant integer, not a constant pointer to an integer. You cannot change the object pointed, but you can change the pointer to refer to a different object.
void change(const int arr[], int size);
That signature is processed by the compiler as void change( const int *arr, int size ), and I'd recommend that you type it as that, as it will reduce confusions. Where the function is called, change(foo,2), the compiler will transform the argument foo (type is int[2]) to &foo[0] which has type const int* (both transformations are commonly called decay of the array to a pointer).
Now as in the first block of code, you cannot change the pointed memory, but you can change the pointer to refer to a different object.
Additionally, in C++ the default mode is pass-by-value. The pointer arr inside change is a copy of the value &foo[0]. Inside the function you are changing that copy, but that will not affect anything outside of the function context.
const int * is doing what it's supposed to do, what's confusing you is its purpose.
Think of it as a pointer to a readonly int. You can point to any int you want, but it's going to be readonly no matter what.
You might use this to loop through an array of type const int, for example.

C++ how to return and collect an address from a function

What return and variable type would I need to use to catch the return value of the address of a variable passed into a function?
Say:
RETURNTYPE get_address(int num){
return &num;
}
int main(){
int num = 1;
DATATYPE = get_address(num);
return 0;
}
RETURNTYPE and DATATYPE should be int*, but note that it does not make much sense to return a pointer to a function argument.
Function argument exists only for as long as the function is executing. Once the function returns that variable no longer exists and using the address returned is essentially undefined behavior.
If you want address of the variable used as argument at the call site then you don't need the function get_address() at all, just use the & operator:
int main(){
int num = 1;
int* pnum = &num;
return 0;
}
If you have access to C++11, you can use the built-in std::addressof.
You can implement a generic function that returns the address of the parameter as such:
template<typename T>
T* addr(T& param)
{
return (T*)&(char&)param;
}
(this is the C++11 implementation, and it's like this because the unary & can be overloaded)
Note that you must pass the parameter by reference otherwise you're returning the address of a local variable, which can result in undefined behavior.
Or you can simply use &. :)
I just need to verify that the address on num is different inside and outside of the function when passed by value.
You can pass the same parameter by value and by reference:
void compareAddresses(int passedByValue, int& passedByReference)
{
std::cout << &passedByValue << " " << &passedByReference;
}
pointer is variable that holds an address. So you need pointer to int.
int* get_address (int num) {
return &num;
}
int main () {
int num = 1;
int* pointer = get_address(num);
return 0;
}
This above of course won't work because you pass the value by copy, and the variable will be deallocated from the stack and the pointer will be invalidated.
If you need a function you should pass it by reference (this will return the correct pointer address of the variable):
int* get_address (int &num) {
return &num;
}
Though you don't need a function. It's a bit excessive. That works just fine:
int* pointer = &num;
You can't, or rather I should say you shouldn't return the address of local scoped variables, as they no longer exist after the function returns. Therefore, you're getting only garbage.
int num = 1;
int* addr = &num;
In C++11 you can use auto when you don't know the type, but you cannot return auto from a function.
auto num = 1;
auto addr = &num;
The local variable gets destroyed after the function has finished. The function call might get over written by other function calls. You wont get what you want. So you shouldn't return a pointer to the local variable of a function.

pointer reference type

I am trying to write a function that takes a pointer argument, modifies what the pointer points to, and then returns the destination of the pointer as a reference.
I am getting the following error: cannot convert int*** to int* in return
Code:
#include <iostream>
using namespace std;
int* increment(int** i) {
i++;
return &i;
}
int main() {
int a=24;
int *p=&a;
int *p2;
p2=increment(&p);
cout<<p2;
}
Thanks for helping!
If you indeed mean "return the destination of the pointer as a reference", then I think the return type you're after is int& rather than int*.
This can be one of the confusing things about C++, since & and * have different meanings depending on where you use them. & is "Reference type" if you're talking about a variable definition or return type; but it means "Address of" if it's in front of a variable being used after it's defined.
I could be completely mistaken, but it seems to me that you've gotten these two meanings mixed up; and since you want to return a reference, you've written "return &i", since & is used for references. However, in this case, it returns the address of i. And since i is a pointer to a pointer to an int, in this line of code:
int* increment(int** i) { i++; return &i;}
you are returning the address of a pointer to a pointer to an int. That is why you are getting your error message cannot convert int***' to int*.
Let's walk through your code line by line. You are after a program that takes a pointer and returns a reference. So that would be:
int& increment(int* i)
We don't need the double pointer that you had in your code (unless you want a pointer to a pointer). Then you want it to modify what the pointer points to:
(*i)++;
And then return the destination of the pointer as a reference:
return *i;
Here, we are dereferencing i. Remember that using references lets you treat them like normal variables, and handles the pointer stuff for you. So C++ will figure out that you want it to be a reference.
Then, to use your code, you can do pretty much what you had, but using less pointers:
int a=24;
int *p=&a;
int *p2;
p2 = increment(p);
I haven't tested any of this, so anyone may feel free to edit my answer and fix it if I've got something wrong.
int* increment(int** i) { (**i)++; return *i;}
and
cout << *p2;