This question already has answers here:
Function does not change passed pointer C++
(4 answers)
Closed 8 years ago.
so right now i am trying to do some nift code for a little game i am making and I've run into something that has been bothering me for a while about pointers.
but first things first, i am trying to have a function take in a void* and give that void* a value, but it seems to not actually stay beyond the function like i'm used to. so...
void ItemGen(void* Holder){
Item* NewItem
NewItem = new Item*
NewItem->Init();
Holder = NewItem;
}
it's not actually making "items" but various kinds of items that inherit from a item, this is just me making it simpler.
Holder gets changed but never make it outside the function, how should i change this, so that it does.
on top of that, i am sort of confused about a certain occurrence that can happen and i just want to know what happens when you do these. or really the difference between them
void *p1;
void *p2;
&p1 = &p2;
p1 = p2;
*p1 = *p2;
oh and is there a way to do a XOR operation on pointers so i can swap them with out a holding pointer.
i feel like i asked very stupid questions, but are confusing simply because they're void *'s.
Pointers are variables like any other, and as such are passed by value to functions. You've simply assigned a new value to the parameter copy of your pointer.
If you want to change a variable you pass to a function you must pass by reference or by pointer. Preferably the former.
void ItemGen(void *& Holder);
BTW, that's a horrible naming convention.
I am answering this point "Holder gets changed but never make it outside the function, how should i change this, so that it does."
void ItemGen(Item** Holder){
Item* NewItem
NewItem = new Item*
NewItem->Init();
*Holder = NewItem;
}
void someotherfunc() {
Holder * holder=0;
ItemGen(&holder)
if(holder!=0) {
holder->dosomething()
}
}
"void" simply means "nothing". A "void*" pointer points to nothing in particular. It's a way of saying "I don't know what kind of thing this pointer points to"; a void* pointer is a catch all that can receive any kind of pointer, but if you want to go from a void* pointer to any other kind, you have to explicitly cast it.
As to your first problem:
If you lived at "1234 Pointer Street", there is nothing magical about the number "1234", it's just a number. It only tells you anything when you treat it as a "pointer" - a house number. It "points" to a house on a particular street.
In the case of a computer, the street is memory.
int a = 0;
int* b = 0;
the variables "a" and "b" both contain the numeric value "0".
b = b + 1;
See? perfectly valid. So
void foo(int a, int* b)
{
a = a + 1;
b = b + 1;
}
void bar()
{
int x = 0;
int* y = 0;
foo(x, y);
// 'x' and 'y' are still zero here, they have to be, or you couldn't do
foo(0, 0);
}
Pointers to have some distinguishing features from regular variables.
int a = 0;
int* b = 0;
a = a + 1; // now a = 1
b = b + 1; // now b = b + sizeof(int) => 4.
What pointers do best is provide values for C/C++'s "dereference" operators.
a = *(b);
Going back to the streets example, if we assigned b our "1234 Pointer Street" address, it would be:
b = 1234;
What if we wanted to deliver something there?
*b
This means: The contents of the address that b describes.
Lets go back to the definition
int* b;
This says: "b is the address of an integer". How do we get the address of a specific integer?
// imagine a set of mailboxes.
int box1, box2, box3, box4, box5;
// lets put something interesting into box 3.
box3 = 5;
// now let's address somethign to box3.
// "&" is the "address of" operator.
int* pointer = &box3;
// now lets put something more interesting in pointer.
pointer = 10;
// whoops - that was wrong, we just changed the ADDRESS to some random numeric value.
// what we mean't was:
*pointer = 10;
printf("box 3 contains %d\n", box3);
// answer? 10, not 5.
After setting "pointer = &box3" we populated "pointer" with the location of box3's storage in memory, so when we wrote to that address using "*pointer = 10" we wrote to the storage address of box3.
You asked about
void *p1;
void *p2;
&p1 = &p2;
p1 = p2;
*p1 = *p2;
"&p1 = &p2" says "the address of p1 is the address of p2" and isn't legal, it wouldn't compile.
"p1 = p2" is legal, but it says "assign the same address as p2 to p1"
"*p1 = *p2" is illegal because you are using void pointers, which point to void, besides, you've just made p1 and p2 be equal to each other so it would be a null operation.
To fix your initial problem, you would need to provide a way for the caller to receive the new value you are creating.
Option 1: Accept a pointer-to-pointer
This is the very old-school C way to do it, but your code doesn't look very C++ so far so I'll list it first.
void ItemGen(void** Holder)
{
Item* NewItem = new Item;
NewItem->Init(); // why doesn't the constructor do this?
// ** means pointer to storage that is itself also a pointer,
// so if we dereference it once we will be refering to the inner pointer.
*Holder = NewItem;
}
Option 2: Return a pointer
void* ItemGen() // Why isn't this "Item*"?
{
Item* NewItem = new Item;
NewItem->Init();
return NewItem;
}
Option 3: Take a reference
void ItemGen(Item*& Holder)
{
Holder = new Item;
Holder->Init();
}
This says "Holder is a reference to a pointer to storage of type Item". It's exactly like a "Item*" pointer except instead of creating a temporary local copy of the value passed in, it's an alias for the value that was passed in.
If you absolutely have to throw away the type information of your pointer:
void ItemGen(void*& Holder)
{
Item* NewItem = new Item;
NewItem->Init();
Holder = NewItem;
}
At the level you appear to be with C++ so far, I would guess that your use of void* pointers is probably misguided.
Related
As a beginner C++ coder, I am losing my head around pointers. I have correctly understood many things (and used them to implement different structures), but this "particular" situation is making me lose my head since Saturday.
If I pass a pointer by value (int* pointer), I am able to edit what it points to, but not the pointer (since it's a copy). And this correctly works. I am okay with that.
// pass a pointer by value (creating a copy)
void editPointerValue(int* pointer)
{
int c = 200;
int *p = &c;
// has no effect. perfect!
pointer = p;
}
if I call this function in my main, and print the pointer, it will stay the same. perfect.
BUT if I call one of these functions BEFORE:
// pass pointer to the pointer (allows pointer editing)
void editPointer(int** pointer)
{
int a = 75;
int *p = &a;
*pointer = p;
}
// pass pointer as reference (allows pointer editing)
void editPointerReference(int*& pointer)
{
int b = 100;
int *p = &b;
pointer = p;
}
Then, my pass-by-value function is allowed to change the pointer too!
what I mean is:
int a = 0;
int pointer = &p;
// (doesn't do anything)
editPointerValue(pointer);
// (correct. prints 0)
cout << *pointer << endl;
// (pointer / sets 75)
editPointer(&pointer);
// (reference / sets 100)
editPointerReference(pointer);
// (by value / shouldn't set to 200. Like before)
editPointerValue(pointer);
cout << *pointer << endl;
// should print 100, instead it prints 200.
I surrender. I don't know why calling another function before, changes the next one's behavior.
Solved: I was invoking Undefined Behavior and it still compiled in weird ways. (with no warning whatsoever)
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I want to change different pointer (different types), that they point to NULL/0/nullptr..., but I have to use a variable to do this! Generally I understand pointers and I know what the problem is, but I don't know how to solve it.
So I need something like
int NULLPOINTER = nullptr; // data type can change if needed
int* myIntPointer = NULLPOINTER;
float* myFloatPointer = NULLPOINTER;
foo* myFooPointer = NULLPOINTER;
As shown above, this is not possible because of the invalid conversion error (int to int*/float*/foo*).
So how can I archiv this?
As requested a more complex example for clarification:
class foo
{
float floatVar;
};
class bar
{
char charVar;
};
void changeSomething(bar* pBarTmp)
{
/* pGlobal is a member of another class and the type is depends on the method */
pGlobal = pBarTmp;
}
int main()
{
/* Working just fine */
int var = 1;
int *pointer = &var;
/* Also working fine */
foo *pointer = 0; //nullptr or NULL or __null (compiler dependend)
/* Not working because newAddress is int and not bar* / foo* / int* */
int newAddress = 0;
// Only one of the following is present, it depends on the
// method/class (just for visualization)
bar *pointer = newAddress;
foo *pointer = newAddress;
int *pointer = newAddress;
changeSomething (pointer);
}
I am not allowed to change int newAddress; into int* newAddress;. Overall I won't use something else than NULL / 0 / nullptr / ...
Another difficulty is, that I cannot use reinterpret_cast cause of coding guidelines.
int* p3 = 1; //Error invalid conversion from int to int
You can directly set the address of a pointer in C++
int* p3 = reinterpret_cast<int*>( 0x00000001 );
But its not good idea since you dont know where the pointer points in memory and de-referencing would lead to undefined behavior.
Its invalid conversion because 1 has type int and it's not possible to assign to pointer variable int * without cast.
int* p2 = 0; //p is a NULL-pointer
Pointers pointing to null should be initialized
int* p2 = nullptr;
instead of
int* p2 = 0;
Since C++11 you can create an instance of std::nullptr_t and assign it to pointers.
std::nullptr_t initAddr;
int* p2 = initAddr;
C++11 came with nullptr, and nullptr has type std::nullptr_t. You can create an instance of this and assign:
int* p1;
char* p2;
double* p3;
std::nullptr_t newAddress;
p1 = newAddress;
p2 = newAddress;
p3 = newAddress;
Demo
This satisfies having your NULL in a variable.
Changing the adress a pointer is pointing to
My goal is to change the adress of different pointer types to NULL
By assignment:
int* p = nullptr;
and I have to use a variable to do this.
int newAdress = 0;
int* p2 = newAdress;
The bug here is that newAdress has the wrong type. The compiler helps you out by telling you that is wrong. You will need to use a pointer (of compatible type) variable to assign a pointer:
int* newAdress = nullptr;
// ^ see here, a pointer
int* p2 = newAdress;
int* p3 = 1;
This assignment makes little sense in most cases. 1 is not null, nor is there usually a guarantee that there is an int object at that memory location.
Nevertheless, there are some special cases where you need a particular address value. That can be achieved with casting:
int* p3 = reinterpret_cast<int*>(1);
If you don't know of such cases, then you don't need to do it. If you don't have such case, then using pointer to the arbitrary memory location has undefined behaviour.
You have to understand that int* ≠ int. You shouldn't directly change the address. That seems pointless, since every program run variables are saved in different parts of memory with different addresses.
It only works with NULL, which is the same as 0, but should be avoided in C++ 11, where you should use nullptr for safety.
What you can do is set the address with the address-of-operator &:
int a;
int* b = &a;
A very general question: I was wondering why we use pointer to pointer?
A pointer to pointer will hold the address of a pointer which in turn will point to another pointer. But, this could be achieved even by using a single pointer.
Consider the following example:
{
int number = 10;
int *a = NULL;
a = &number;
int *b = a;
int *pointer1 = NULL;
pointer1 = b; //pointer1 points to the address of number which has value 10
int **pointer2 = NULL;
pointer2 = &b; //pointer2 points to the address of b which in turn points to the address of number which has value 10. Why **pointer2??
return 0;
}
I think you answered your own question, the code is correct, what you commented isn't.
int number = 10; is the value
int *pointer1 = b; points to the address where int number is kept
int **pointer2 = &b; points to the address where address of int number is kept
Do you see the pattern here??
address = * (single indirection)
address of address = ** (double indirection)
The following expressions are true:
*pointer2 == b
**pointer2 == 10
The following is not!
*pointer2 == 10
Pointer to pointer can be useful when you want to change to what a pointer points to outside of a function. For example
void func(int** ptr)
{
*ptr = new int;
**ptr = 1337;
}
int main()
{
int* p = NULL;
func(&p);
std::cout << *p << std::endl; // writes 1337 to console
delete p;
}
A stupid example to show what can be achieved :) With just a pointer this can not be done.
First of all, a pointer doesn't point to a value. It point to a memory location (that is it contains a memory address) which in turn contains a value. So when you write
pointer1 = b;
pointer1 points to the same memory location as b which is the variable number. Now after that is you execute
pointer2 = &b;
Then pointer2 point to the memory location of b which doesn't contains 10 but the address of the variable number
Your assumption is incorrect. pointer2 does not point to the value 10, but to the (address of the) pointer b. Dereferencing pointer2 with the * operator produces an int *, not an int.
You need pointers to pointers for the same reasons you need pointers in the first place: to implement pass-by-reference parameters in function calls, to effect sharing of data between data structures, and so on.
In c such construction made sense, with bigger data structures. The OOP in C, because of lack of possibility to implement methods withing structures, the methods had c++ this parameter passed explicitly. Also some structures were defined by a pointer to one specially selected element, which was held in the scope global to the methods.
So when you wanted to pass whole stucture, E.g. a tree, and needed to change the root, or 1st element of a list, you passes a pointer-to-a-pointer to this special root/head element, so you could change it.
Note: This is c-style implementation using c++ syntax for convienience.
void add_element_to_list(List** list, Data element){
Data new_el = new Data(element); // this would be malloc and struct copy
*list = new_el; //move the address of list, so it begins at new element
}
In c++ there is reference mechanismm and you generally you can implement nearly anything with it. It basically makes usage of pointers at all obsolete it c++, at least in many, many cases. You also design objects and work on them, and everything is hidden under the hood those two.
There was also a nice question lately "Why do we use pointers in c++?" or something like that.
A simple example is an implementation of a matrix (it's an example, it's not the best way to implement matrices in C++).
int nrows = 10;
int ncols = 15;
double** M = new double*[nrows];
for(unsigned long int i = 0; i < nrows; ++i)
M[i] = new double[ncols];
M[3][7] = 3.1416;
You'll rarely see this construct in normal C++ code, since C++ has references. It's useful in C for "passing by reference:"
int allocate_something(void **p)
{
*p = malloc(whatever);
if (*p)
return 1;
else
return 0;
}
The equivalent C++ code would use void *&p for the parameter.
Still, you could imagine e.g. a resource monitor like this:
struct Resource;
struct Holder
{
Resource *res;
};
struct Monitor
{
Resource **res;
void monitor(const Holder &h) { res = &h.res; }
Resource& getResource() const { return **res; }
}
Yes, it's contrived, but the idea's there - it will keep a pointer to the pointer stored in a holder, and correctly return that resource even when the holder's res pointer changes.
Of course, it's a dangling dereference waiting to happen - normally, you'd avoid code like this.
I was reading through MIT's Introduction to C++ and one code example showed:
int *getPtrToFive() {
int *x = new int;
*x = 5;
return x;
}
int main() {
int *p;
for (int i = 0; i < 3; ++i) {
p = getPtrToFive();
cout << *p << endl;
delete p;
}
}
I was wondering why it is possible to delete "p" after every iteration despite "p" being declared once before the loop started and was not allocated using "new".
Another question is when "*x" is assigned the value 5 in the function, since it is a pointer the memory address would be changed right? So it would be something like 0x00005 instead of the actual value 5?
I was wondering why it is possible to delete "p" after every iteration despite "p" being declared once before the loop started and was not allocated using "new"
No. You are not deleting p, you are deleting the object p points to, which is allocated using new each iteration.
Another question is when "*x" is assigned the value 5 in the function, since it is a pointer the memory address would be changed right? So it would be something like 0x00005 instead of the actual value 5?
The value of x would be something like 0xFFd00whatever. but you are printing the value of *x, which is "the number that is in the memory at address 0xFFd00whatever". There is no x=5 in your code; there's only *x=5. It means "go to the address to which x points to, and put the number 5 in there".
You can think about it this way: you have a hand, okay? let's call it "x". The command
x = new int;
Means "point your finger at some empty place on your desk." Where
*x = 5;
Means "draw the number five where your hand points to".
p is simply a variable of the type int* (pointer to int). Its value is an address. When you assign a new value to it then it points to a new object. delete expects an address; that's all it needs to deallocate the memory you allocated.
The variable used to store said address is irrelevant. It's value has changed, and that's all delete cares about; the value.
So i have a reasonable understanding of pointers but i was asked what the difference between these are:
void print(int* &pointer)
void print(int* pointer)
I'm still a student myself and im not 100%. Im sorry if this is basic but my googleing skills failed me. Is there anyway you can help me understand this concept a bit better. I haven't used c++ in a long time, and i am trying to help to tutor a student, and i am trying to solidify my conceptual knowledge for her.
The first passes the pointer by reference, the second by value.
If you use the first signature, you can modify both the memory the pointer points to, as well as which memory it points to.
For example:
void printR(int*& pointer) //by reference
{
*pointer = 5;
pointer = NULL;
}
void printV(int* pointer) //by value
{
*pointer = 3;
pointer = NULL;
}
int* x = new int(4);
int* y = x;
printV(x);
//the pointer is passed by value
//the pointer itself cannot be changed
//the value it points to is changed from 4 to 3
assert ( *x == 3 );
assert ( x != NULL );
printR(x);
//here, we pass it by reference
//the pointer is changed - now is NULL
//also the original value is changed, from 3 to 5
assert ( x == NULL ); // x is now NULL
assert ( *y = 5 ;)
The first passes the pointer by reference.
If you pass by reference the function can change the value of the passed argument.
void print(int* &pointer)
{
print(*i); // prints the value at i
move_next(i); // changes the value of i. i points to another int now
}
void f()
{
int* i = init_pointer();
while(i)
print(i); // prints the value of *i, and moves i to the next int.
}