Pass a pointer to a function that receives a reference? - c++

I have a function similar to this:
#include <iostream>
#include <string>
void increaseRef(int& x) {
x += 3;
std::cout << x << std::endl;
}
Now I have a pointer that should be passed to this function, I can deference it:
int main(int argc, char const* argv[])
{
int* x;
*x = 3;
increaseRef(*x);
return 0;
}
Or not:
int main(int argc, char const* argv[])
{
int* x;
*x = 3;
increaseRef(x);
return 0;
}
In the second case I got an error:
main.cpp:15:15: error: invalid initialization of reference of type ‘int&’ from expression of type ‘int*’
increaseRef(x);
In the first case I got a segfault.

First of all, you can't do this:
int* x;
*x = 3;
because x doesn't point to a valid int. De-referencing it us undefined behaviour.
You could do this:
int y = 3;
int* x = &y;
Then you can pass *x to the function.
increaseRef(*x);

After the edit, I see your point better.
In the second case, you are referencing the reference itself.
In other terms, you are giving an &(int*) to the function instead of an &(int).
Otherwise:
You are not allocating any memory for your pointer.
You need to call malloc() or new() before you can dereference the pointer.
Try
int *x=new int;
*x=3;
increaseRef(*x);
delete x; //and don't forget to delete your pointers, or you will leak memory.
return 0;
You can also pass the allocation to c++ by defining a local variable, as #juanchopanza stated. That way, memory will be automatically freed on return (and the variable will be created on the stack), the downside being that after your function defining the given variable returns, your pointer will be invalid, and if you dereference it outside the function, you will get a segfault.

Related

why cout statement is not working after pointer initialization?

cout statement is not working after pointer initialization. And this code gives me a segmentation fault.
#include <iostream>
using namespace std;
int main()
{
int *p;
*p=12;
cout<<"NOW THIS STATEMENT WILL NOT WORK";//BUT WHY?
cout<<*p;
return 0;
}
You didnt initialize the pointer:
int *p;
p points "nowhere", it is not initialized, its value is indeterminate. When you dereference it in the next line:
*p=12;
You cause undefined behavior, because p does not point to an int. There is no int where you could store 12.
If you want to store an int somewhere, you need an int not just a pointer to an int:
int x = 0;
int *p = &x;
*p=12; // same as x = 12;

Function with pointer return type

I'm trying to understand pointer return types from functions.
The following example produces a type conversion error.
#include <iostream>
using namespace std;
int* abc(int* y)
{
int x=y;
int *z = &x;
x++;
return z;
}
int main()
{
int *a = abc(100);
int b = *a;
cout << a <<endl;
cout << b <<endl;
return 0;
}
The error message is:-
In function 'int* abc(int*)': 6:11: error: invalid conversion from 'int*' to 'int' [-fpermissive]
In function 'int main()': 14:19: error: invalid conversion from 'int' to 'int*' [-fpermissive]
4:6: note: initializing argument 1 of 'int* abc(int*)'
How to resolve the above error and also what is the difference between the following function forms and their appropriate calling syntax,
int* function()
int * function()
int *function()
The argument type in
int* abc(int* y)
is int*. When you call the function,
int *a = abc(100);
you are passing 100, an int. It is not a pointer to an int.
You can fix the problem by using:
Option 1
Change the argument type.
int* abc(int y) { ... }
Option 2
Change the way you call the function.
int x = 100;
int *a = abc(&x);
If you follow this option,
The line
int x=y;
needs to be modified. Type of y is int*, not int. You'll have to change the line to:
int x=*y;
Problem
You are returning the address of a local variable from the function. Dereferencing that address in the calling function is undefined behavior.
When you return an address from a function and the calling function dereferences that address, the address needs to be valid in the calling function. One way to do that is to allocate memory from heap using malloc.
int* abc(int* y)
{
int* x = malloc(sizeof(int));
*x = (*y + 1);
return x;
}
When you do that, you'll have to remember to call free in the calling function.
int x = 100;
int *a = abc(&x);
// Use a
// Deallocate memory
free(a);
The problem is not your return type. Your problem is on this line:
int x=y;
Here y is a pointer and you're trying to assign it to x which is an int.
You're also passing a literal 100 which is an int to the abc function which takes a pointer as an argument.
Finally, there is no difference between the types of the 3 functions you give. Whitespace is insignificant in this context.
Your first two statements in both functions are incorrect. 100 is not a pointer when main calls abc, and blindly assigning y to x won't work because the former is an int and the latter is an int pointer.

How to define an alias to a pointer to an integer?

I am trying to run the following code, but I am getting the following error.
error: cannot declare pointer to 'int&'
#include <iostream>
using namespace std;
int main()
{
int x = 5;
int *ptr = &x;
int &(*y) = ptr;
*y = 5;
cout << *ptr << endl;
return 0;
}
You declare references to pointers the same way you declare references to basic types.
Consider:
int main()
{
int i = 0; // int
int& ir = i; // int reference (reference to int)
int* ip = &i; // int pointer (pointer to int)
int*& ipr = ip; // int pointer reference (reference to pointer to int)
*ip = 5;
cout << *ipr << endl;
return 0;
}
If you just want a new pointer to the same region of memory, use:
int *y = ptr;
This not so much an "alias" in that if you change *ptr or *y, both will change, but if you change the pointers themselves, the other will not be updated.
If you actually do want a reference to a pointer, use:
int *&y = ptr;
int *ptr = &x;
pointer value has an address and a type of x.
when you typed code above, the value of ptr is an address of x, and ptr know the type of x.
int * (&y) = ptr;
the code above is declaring variable 'y' (type:int*, define:ptr's reference)
reference variables should be declared and defined simultaneously.
anyway, as a result, ptr and y are pointing same memory address.
you can easily think y is a nickname of ptr.
so you can access the variable 'x' by using y, instead of ptr.
v - a variable name.
&v - a variable that will be a reference of something.
*&v - a variable that will be a reference of a pointer to something
int *&v - a variable that will be a reference of a pointer to int
Or for a more interesting example,
(*&v)[5] - a variable that will be a reference of a pointer to an array of 5 something
int (*&v)[5] - a variable that will be a reference of a pointer to an array of 5 int

Compilation error while passing double pointer in cpp

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
void f(char **x)
{
(*x)++;
**x = 'a';
}
int main()
{
char str[]="hello";
f(&str);
cout << str << endl;
return 0;
}
Please tell me why this program is giving compilation Error.I am using the g++ compiler
Error :temp1.cpp:16:8: error: cannot convert ‘char (*)[6]’ to ‘char**’ for
argument ‘1’ to ‘void f(char**)’
Arrays can be implicitly converted to pointers, but that doesn't mean that the implicit "pointer equivalent" already exists.
You are hoping that f(&str); will implicitly create both a pointer to str and a pointer to that pointer.
This small (working) change illustrates this point:
int main()
{
char str[]="hello";
char *pstr = str; // Now the pointer extists...
f(&pstr); // ...and can have an address
cout << str << endl;
return 0;
}
You are passing pointer of constant char to the function but in function you are taking it as pointer of pointers. That is the problem. I commented out below where the problem lies.
[Off topic but N. B. : Arrays and pointers are different concept.]
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
void f(char **x) //**x is pointer of pointer
{
(*x)++;
**x = 'a';
}
int main()
{
char str[]="hello";
f(&str); //You are passing pointer of constant char.
cout << str << endl;
return 0;
}
You're going to run into a serious problem with your function f since &str and &str[0] both evaluate to the same value ... as other posters have pointed out, these operations point to different types, but the actual pointer r-value will be the same. Thus in f when you attempt to double-dereference the char** pointer x, you're going to get a segfault even if you attempted something like a cast to massage the type differences and allow compilation to happen with errors. This is because you are never getting a pointer-to-pointer ... the fact that &str and &str[0] evaluate to the same pointer value means that a double-dereference acually attempts to use the char value in str[0] as a pointer value, which won't work.
Your problem is that you're treating arrays as pointers, when they're not. Arrays decay into pointers, and in this case, it doesn't. What you're passing in is a char (*)[6] when it expects a char **. Those are obviously not the same.
Change your parameter to char (*x)[6] (or use a template with a size parameter):
template <std::size_t N>
void f(char (*x)[N])
Once inside, you try to increment what x is pointing to. You can't increment an array, so use an actual pointer instead:
char *p = *x;
p++;
*p = 'a';
All put together, (sample)
template <std::size_t N>
void f(char(*x)[N])
{
if (N < 2) //so we don't run out of bounds
return;
char *p = *x;
p++;
*p = 'a';
}

What does *& mean in a function parameter

If I have a function that takes int *&, what does it means? How can I pass just an int or a pointer int to that function?
function(int *& mynumber);
Whenever I try to pass a pointer to that function it says:
error: no matching function for call to 'function(int *)'
note: candidate is 'function(int *&)'
It's a reference to a pointer to an int. This means the function in question can modify the pointer as well as the int itself.
You can just pass a pointer in, the one complication being that the pointer needs to be an l-value, not just an r-value, so for example
int myint;
function(&myint);
alone isn't sufficient and neither would 0/NULL be allowable, Where as:
int myint;
int *myintptr = &myint;
function(myintptr);
would be acceptable. When the function returns it's quite possible that myintptr would no longer point to what it was initially pointing to.
int *myintptr = NULL;
function(myintptr);
might also make sense if the function was expecting to allocate the memory when given a NULL pointer. Check the documentation provided with the function (or read the source!) to see how the pointer is expected to be used.
Simply: a reference to a pointer.
In C, without references, the traditional way to "relocate" a pointer, is to pass a pointer to a pointer:
void c_find(int** p, int val); /* *p will point to the node with value 'val' */
In C++, this can be expressed by the reference syntax, to avoid the awkward double dereference.
void cpp_find(int*& p, int val); // p will point to the node with value 'val'
It means a reference to a pointer to an int. In other words, the function can change the parameter to point to something else.
To pass a variable in, just pass an int*. As awoodland points out, what's passed in must be an l-value.
Edit:
To build on awoodland's example:
#include <iostream>
void foo(int*& var)
{
delete var;
var = new int;
}
int main(int argc, char* argv[])
{
int* var = NULL;
std::cout << var << std::endl;
foo(var); // this function can/will change the value of the pointer
std::cout << var << std::endl;
delete var;
return 0;
}
function takes a single parameter, mynumber which is a reference to a pointer to an int.
This is useful when you need to pass a pointer to a function, and that function might change the pointer. For example, if you function is implemented like this:
function(int*& mynumber)
{
if( !mynumber )
mynumber = new int;
*mynumber = 42;
}
...Then something like this might happen in the calling code:
int main()
{
int* mynumber = 0;
function(mynumber); // function will change what "mynumber" points to
cout << *mynumber;
return 0;
}
This is a reference to a pointer to int - you would have to pass in the address of an int to this function, and be aware that the function could change the pointer through the reference.
Dumb example:
void func(int*& iref)
{
iref = new int;
}
int main()
{
int i(0);
int* pi(&i);
func(pi);
// pi no longer equal to &i
return 0;
}