I'm playing around with pointers to understand this concept better
and wanted to ask
Why do i get null pointer as return for the second function?
and why it isn't possible to get the address 0x7fff15504044.
What is happening and where inside memory is the integer 5 stored,
when im working with it inside the function?.
#include <iostream>
using namespace std;
int* return_adress(int* input){ return input; }
int* return_adress_from_input(int input){ return &input; }
int main(){
int k = 3;
cout << return_adress(&k) << endl;
cout << return_adress_from_input(k) << endl;
}
Output:
0x7fff15504044
0
With int* return_adress_from_input(int input), input is a value copy of k in the caller. They are two different variables therefore with different addresses.
input goes out of scope conceptually once the closing brace of the function is reached.
The pointer &input then points to memory that you no longer own, and the behaviour of reading that pointer value (let alone dereferencing it) is undefined prior to C++14, and implementation defined from and including C++14.
Because you pass input by value, not by reference. Compiller first creates a local copy of input and then returns address of this local copy. To get the variable address use
int* return_adress_from_input(int& input){ return &input; }
In general, you get undefined behavior which can lead to returning nullptr in the particular case
On my PC i get
00AFFC80
00AFFBA8
so you are just lucky with zero return
Related
When you initialize a pointer with nothing(NULL), that element still has a memory address big enough for the initialising type of that pointer(4 bytes for int, 1 for char etc.) but why,since it's tehnically nothing, not even the value zero? I mean, NULL can't be a fixed value like 0 because zero still is considered a value, so it is something more than that?
Example:
#include <iostream>
int *a=NULL;
int main()
{
std::cout <<&a; //it will show the address in hexadecimal system;
return 0;
}
Your program does not answer the question you were asking. This program shows that, yes the pointer has an address, it needs one to store the value (the address it is pointing to). When you print the value you see that it is indeed nullptr (since this is C++ not C).
#include <iostream>
int *a= nullptr;
int main()
{
std::cout << &a << '\n'; // Will show the address OF THE POINTER in hexadecimal system;
std::cout << a << '\n'; // Will show the address at a is pointing to.
return 0;
}
Output:
0x601180
0
I'm pretty sure there's a duplicate, but I don't see any now. You confuse the meaning of operators * and & in different contexts.
Here, &p means "address of p". And what is p? p is a global variable of pointer type. It is perfectly valid to take address of any global variable.
So, to clear things up:
#include <iostream>
int *a=NULL;
int main()
{
std::cout << &a; //perfectly valid, address of p, type int** (pointer-to-pointer-to-int)
std::cout << a; //still valid, it gives address to where p is pointing, i.e. 0 (NULL)
std::cout << *a; //wrong, dereferencing an invalid address, there's no memory allocated
return 0;
}
You also seem to have few misconceptions about pointers:
"that element still has a memory address big enough for the initialising type of that pointer(4 bytes for int, 1 for char etc.)"
Not at all. Pointer is just a pointer. It doesn't care where does it point to. In fact, on lower levels it's just plain int. It can point to an array, to an element, to nothing at all or to some wild place where nothing was ever stored.
"NULL can't be a fixed value like 0 because zero still is considered a value, so it is something more than that?"
Again, pointer is just a pointer. Pointer doesn't know anything at all about value. Value may or may not exist, and the memory where pointer points to may or may not be valid. And in fact, NULL is defined to be exactly 0 (or nullptr in newer standards): https://en.cppreference.com/w/cpp/types/NULL
As a beginner in C++, first thing I came accross for functions is that they use a copy of the argument, for example if we execute this :
void add (double x){
x=x+3;
}
int main(){
double x=2 ;
add(x) ;
}
Then x would actually be equal to 2, not 5. Later on, learning about pointers, I found the following :
void fill (int *t){
for (int j=0, j<10, j++){
t[j]=j;
}
int main(){
int* p;
p = new int[10];
fill(p);
}
Now if we print what p contains, we find that it's indeed filled by the integers. I have some trouble understanding why it does that as I feel like it should have been the same as the first function ?
Thanks.
The reason it isn't the same as the first function is because you are passing the pointer by value. This means that if you modify the actual pointer, e.g by assigning to it, then it would only be in that state inside the function. The value that the pointer points to is still the original value, which will get modified since both copied pointers point to that same original value (don't forget notation of the form a[i] is equivalent to *(a + i), which does a dereference and is modifying the pointed value, not the pointer itself).
A small example that illustrates this would be the following (not accounting for memory leaks):
#include <iostream>
int test(int* x)
{
int* y = new int{10};
x = y;
std::cout << "Inside function: " << *x << "\n";
}
int main()
{
int* t = new int{5};
std::cout << "Before function: " << *t << "\n";
test(t);
std::cout << "After function: " << *t << "\n";
}
In first example you are using ordinary variable. When passing normal variable to function, like this, the function creates its own copy of the variable (it has same value as it has when you passed it, but it was copied to different place in memory). That is standard behaviour.
In second example you are using pointer: we can say that it points to the place in memory, where values are stored. Few of the advantages of them:
1) If you want to spare memory, but need to use same value in different functions -> mostly appplies to bigger objects than double, like array in your example
2) If you need to change value of variable/array/object in different functions
But careful, in the second function you still created copy, but not of value, but pointer. So basically, the "new" pointer is different object, but it is pointing to the same place in memory, so when accessing the value (which you are doing with [j]), you are editing the same place in memory.
It is not that easy concept to grasp, especially with more dimentional arrays, but hope this helped a little. You can learn some more in tutorials or c++ docs, for example this is a good one: https://www.geeksforgeeks.org/pointers-in-c-and-c-set-1-introduction-arithmetic-and-array/
I have an Eigen matrix to be converted to a C array. I can replicate the issue with the following example.
#include <iostream>
#include <Eigen/Core>
int *test()
{
Eigen::MatrixXi arr = Eigen::MatrixXi::Ones(6,1);
// just to check
arr(4)=3;
arr(5)=19;
return arr.data();
}
int main()
{
int *c_arr;
c_arr = test();
for (int i=0; i<6;++i)
{
std::cout << c_arr[i] << std::endl;
}
return 0;
}
Output:
0
0
1
1
3
19
Now if I print the converted C array values from within the test function the values are correct. However if I print the values from main (as shown above) the first two indices are always garbage. So I am wondering what is happening in the function call? I have tried this with different Eigen matrices (types, sizes) and I get the same result.
I'll start by saying I'm not 100% familiar with the Eigen library (just downloaded it to look at it out of curiosity) and it's documentation is a bit lacking but your problem is a fundamental C problem that can be remedied a few ways.
First we'll start by explaining what's happening in your code to give garbage values:
int *test()
{
/* create an auto scoped variable on the stack;
this variable is only "visible" to this function
and any references to it or it's underlying data
outside the scope of this function will result
in "undefined behaviour" */
Eigen::MatrixXi arr = Eigen::MatrixXi::Ones(6,1);
arr(4)=3;
arr(5)=19;
/* arr.data() is defined as returning a pointer to the scalar underlying type (or
a C-style array in other words). Regardless of the type being returned, it is pointer based
and you are returning a pointer to a location in memory, not the actual data being held in
the memory. */
return arr.data();
} /* the variable arr is destroyed here since we left function scope and the return value (the pointer location)
is put in the return register and "program flow" is returned back to the main function where the pointer being
returned now points to "invalid" memory */
int main()
{
int *c_arr; // create a pointer type that can reference int types
c_arr = test(); // point it to the result of the test function (see notes above)
/* c_arr now points to a memory location returned from test, but since the
arr variable no longer exists here, when you go through and print the values pointed
to at those memory locations you will get what is at those locations and could be "anything"
except a valid reference to the original arr variable and it's underlying data. */
for (int i=0; i<6;++i)
{
std::cout << c_arr[i] << std::endl;
}
return 0;
}
So that's the why, as for how to fix it there are a couple of ways to go about your problem; one is to pass the return array in as a variable in to your test function (e.g. void test(int*& val)), you could then choose to allocate new memory to the variable in the test function, or assume the user has already done so, and must also assume the user will clean up after themselves and call delete[] (not just delete since you're operating on arrays of data).
But this has many caveats of needing to know how much space to allocate and being sure to deallocate when done. I'm not sure why you specifically need a C-style array but since you're using C++, it might be more prudent if you use some of the STL and container functions available to you to help you out, example:
#include <iostream>
#include <vector>
#include <Eigen/Core>
std::vector<int> test()
{
Eigen::MatrixXi arr = Eigen::MatrixXi::Ones(6,1);
arr(4)=3;
arr(5)=19;
// we need the size so we know how big of a container to allocate
std::size_t sz = arr.innerSize() * arr.outerSize();
std::vector<int> ret(sz);
// get a temporary C array pointer so we can reference the data
int* tmp = arr.data();
// copy from tmp[0] to tmp[sz] and insert the data into the first element of ret
std::copy(tmp, tmp+sz, ret.begin());
// return the (copied) data
return ret;
}
int main()
{
std::vector<int> c_arr = test();
// c_arr now points to valid data it holds and can be iterated on
for (std::size_t i = 0; i < c_arr.size(); ++i) {
std::cout << c_arr[i] << std::endl;
}
// if you need a C-style array from here, you can easily copy the data
// from the vector to your C-array
return 0;
}
I looked into using the cast() function of the class, but could not quite figure out the syntax to make it less painful than just copying it the above way since it looks like you'd have to call the cast function to a differnt Eigen type and then cast again from there, but know there is a cast function and other methods to get the underlying data of the MatrixX classes if you need access to it.
I hope that can help.
I am having a problem in my code right now. I can't seem to get what I need and return the address of my structure "b" so other functions can use it. If you can help me out that would be great!
Here is my necessary code:
int notFound = 0;
int choiceNumber;
int arraySize;
Basketball * b;
b = readFile(arraySize, notFound, &b);
Here is the function that I am having the problems:
Basketball * readFile(int & arraySize, int & notFound, Basketball * &b)
{
ifstream inputFile;
inputFile.open("games.txt");
if(inputFile.fail())
{
cout << "The file name \"games.txt\" was not found!" << endl;
notFound = 1;
}
else
{
inputFile >> arraySize;
b = new Basketball [arraySize];
for (int i = 0; i < arraySize; i++)
{
inputFile >> b[i].visitTeam >> b[i].homeScore >> b[i].visitScore;
}
return & b;
}
}
My build errors are these:
Error: invalid intialization of non-const reference of type basketball*& from an rvalue of type Basketball**
Error: In passing arguement 3 of Basketball* readfile(int&,int&, Basketball*&)
Error: Cannot convert Basketball** to Basketball* in return
If you can point me in the right direction that would be great!
The variable b already is a pointer, using &b will create a pointer to the pointer. Drop the address-of operator &.
The error message is very clear about it, same with you returning a pointer to a pointer when you declared is a returning only a single pointer.
"return b;" is what yoy want, not "return &b"
&b Is the address of Basketball*, so you would end with incorrect Basketbal**
As others already wrote, since b is already a pointer, return b; will fix your error.
If you do return &b; you are returning the address of a pointer, i.e. a "double level indirection" pointer, which would be a Basketball**.
However, let me add that you may simplify your C++ code using more modern idioms, like using std::vector<Basketball> instead of raw pointers and raw arrays, e.g.:
std::vector<Basketball> readFile(int & notFound);
Note that a vector knows its own size (e.g. you can call its size() method to query for it), so you don't need a separate reference parameter to store the size.
And, moreover, a vector automatically cleans up its content, thanks to its destructor. So, you don't put a burden on the caller to make an explicit call to delete[] to release the allocated array.
As an alternative, you could use a bool parameter meaning "not found", and pass the vector as non-const reference, e.g.:
// Returns false if not found, true if found
bool readFile(std::vector<Basketball>& v);
Or, depending on your design, you may even return a std::vector, and throw an exception in the not-found case.
newbie question here, can anybody provide an answer to why this loop is not terminating? I am refrencing the address of the variable, then de-referencing it and adding one to it. By my logic it should terminate by ~ the 10th step.
Thanks!
#include <iostream>
using namespace std;
int addtoi(int intern);
int main(){
for(int i = 0; i < 10;addtoi(i)){
}
}
int addtoi(int intern){
int *pt;
pt = &intern;
++*pt;
cout << *pt << "\t" << intern << "\n";
return 0;
}
Your loop is not terminating because any changes that you made to intern inside addtoi stay inside addtoi. The fact that you take a pointer there has no effect, because it's too late: you are taking a pointer of a local variable, which is a copy of i passed in.
You can fix this by passing in intern by reference, like this:
int addtoi(int& intern) {
intern++;
cout << intern << "\n";
return 0;
}
You do not need to take its address - simply modifying it will change the value of i inside the loop.
You don't change the value of i anywhere in your loop. You do pass its value to addtoi, but passing a value can't change the value of the variable whose value you took. So why would it ever end?
If you pass a reference or pointer to i to addtoi, then it can change i's value. But if you only pass the value itself, then it can only change the value passed to it, which has no effect on i's value.
What do you think would happen if you did this:
addtoi(1);
Do you think that constant 1 would somehow change? Same thing -- if you pass a value, you can't change anything in the caller since all you got was a value.
Consider:
int j = 1;
int i = 1;
addtoi(i);
addtoi(j);
addtoi(1);
These three calls all pass the same value to addtoi, 1. It makes no difference how you obtain that value if all you pass is the value.
The loop is not terminating because when you do addtoi(i), the value of i is send to the addtoi() function and not the original i variable. Its a classic example of pass by value.