Task: I want to swap pointers without reference passing the pointers in the function.
Problem 1: The following code does the job but I think its swapping the "data" instead of swapping the "pointers".
void swappointers(char *ptrX, char *ptrY)
{
char dummy;
dummy = *ptrX;
*ptrX = *ptrY; //LINE
*ptrY = dummy;
}
Problem 2: How the commented line is working? *ptrX means that ptrX is being de-referenced(accessing the value the pointer is directing to). Similar is the case with *ptrY. But why the value being directed by ptrX is being changed here? I mean its actually looking like this:
ValueofX = ValueofY
Thank you :)
Edit:
Solved the first problem.
void swappointers(char **ptrX, char **ptrY)
{
char *dummy = nullptr;
dummy = *ptrX;
*ptrX = *ptrY;
*ptrY = dummy;
}
I think its swapping the "data" instead of swapping the "pointers".
You are correct.
I want to swap pointers without reference passing the pointers in the function.
That's impossible. Unless you pass by reference, changes made inside the function will not be seen by the caller.
template<typename T>
void swap(T &a, T &b){
T backup=a;
a=b;
b=backup;
}
*ptrX = *ptrY; means variable, to which points ptrX, have to have same value as variable to which points ptrY.
About your commented line:
*ptrX = *ptrY; //LINE
In plain English it means:
Put the value of the memory location pointed to by ptrY into the memory location pointed to by ptrX.
Related
I'm reading a piece of code which does this
void *ptr_to_something = (void*)0x23; // I made this up, it's just a pointer to something
void *addr;
void *dst = (void*)(addr = ptr_to_something); // This is the line that confuses me
it seems to assign a pointer to something to another pointer of the same thing. And that's okay.. but then the result is enclosed in parenthesis, cast to the same thing and somehow reassigned to a third pointer to the same thing.
Is this valid C++ at all? Is it guaranteed that assigning the result of an assignment yields the same assigned object?
It is valid in C++ to do:
int a, b, c;
a = b = c = 1;
So, therefore the result of an assignment is the value of that assignment.
What the cast is for, is a mystery*. Have you tried removing it, and does that generate a warning?
*not a mystery, just perhaps unnecessary.
This is valid C++. The choice to format the code this way is odd and not advised, but it's perfectly legal.
This code is equivalent to this (what I consider to be better written) code:
void *ptr_to_something = (void*)0x23;
void *addr = ptr_to_something;
void *dst = addr;
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.
The purpose of this function is to take a struct, and enlarge the array by 1. It does this by copying the array to a temporary array, deleting and recreating the original with a larger size. My problem is that when I run the function, all of my values within the struct become '-17891602'.
Correct me if I'm wrong, but I believe that this is the value that shows when the variable has been deleted? I can't figure out the problem. But here's the definition.
void Array::addValueStruct(int id, int size, int type, int compareValue, StoredData temp[])
{
//struct
StoredData* tempStruct = new StoredData [arrSize+1];
for (int i=0;i<arrSize;i++)
{
tempStruct[i] = temp[i];
}
arrSize = arrSize + 1;
delete [] temp;
temp = tempStruct;
temp[arrSize-1].id = id;
temp[arrSize-1].size = size;
temp[arrSize-1].type = type;
temp[arrSize-1].compareValue = compareValue;
}
Also, not sure if this is helpful, but the function call.
test.addValueStruct(5,5,5,5,testData);
UPDATE: Problem solved!
The issue is that the array pointer is passed into the function by value. This means that when you reassign it to point to a different array, this change does not propagate back to the caller.
You need to pass it either by pointer or by reference.
You are passing temp by value. Therefore, addValueStruct gets its own copy and changes made to it are not visible outside that function scope.
The problem probably is this line here:
temp = tempStruct;
Here you only changing the local copy of the temp variable. If you want to modify the variable used for the call you have to pass it by reference.
I'm used to program in C# or Java, so I'm doing really bad in C++. I believe it's easy but I just can't make this work. Please help me.
I have this:
void swap(vector * vet, int i, int j)
{
int temp = vet[i];
vet[i] = vet[j];
vet[j] = temp;
}
I'm calling the method this way:
swap(&vet, j, j - 1);
What I want is to pass the vector using pointers instead of using value.
Obs: The code compiles well without the "*" and "&".
Please don't say that I have to at least try to study pointers, because I did. I just can't make this damn thing work!
You should take the vector by reference rather than "pass by pointer".
void swap(std::vector<int>& vet, std::size_t i, std::size_t j)
{
using std::swap;
swap(vet[i], vet[j]);
}
http://en.cppreference.com/w/cpp/algorithm/swap
Note the more idiomatic:
http://en.cppreference.com/w/cpp/algorithm/iter_swap
Everyone has thus far responded by telling you to use references, which is correct, but they fail to explain why your code doesn't work. The problem here is that you do not understand pointer arithmetic.
Let's say we have a a pointer to 10 ints:
// best to use a vector for this, but for the sake of example...
int *p = new int[10];
Now, if we want to change the value of the second int in that chunk of memory we can write:
*(p + 1) = 20;
Or, the equivalent:
p[1] = 20;
See? Those two lines do the same thing. Adding n to a pointer increases the address of the pointer by n * sizeof *p bytes. Pointer arithmetic is convenient because it hides the sizeof bit from you and allows you to work with logical units (elements) instead of bytes.
So, knowing that, back to your broken code:
vet[i] = vet[j];
This indexes i * sizeof *vet bytes away from the pointer, i.e., i full vectors away from the base address. Obviously that is wrong, you wanted to invoke operator[] on the vector, i.e., treat it as an array. It is not an array however, so the correct syntax would be:
(*vec)[i]
Or
vec->operator[](i);
That said... just use a reference. Safer (object guaranteed to be valid) and idiomatic.
You can try something like....
void swap(vector<int> &vet, int i, int j)
{
int temp = vet[i];
vet[i] = vet[j];
vet[j] = temp;
}
and call your swap function as
swap(vet,i,j);
Bottomline: Use reference variables.They are more like reference in Java.
In fact, in C++ you'd just say
using std::swap;
swap(vet[i], vet[j]);
I have an array of type T which I pass as a pointer parameter to a function.
The problem is that I can't write new data to this array properly, without getting memory violation at the second try.
In this code I read integers from a text file and pass them to the function (part of template class of type T), in order to append them to the array.
After I finish to append the integers, I want to use the same array back in the Main.
Does someone know what's wrong with the code?
Thanks, Max
template<class T> int CFile<T>::read(T **apBuf, int aNum)
{
int readCounter = 0;
*apBuf = (T*)malloc(sizeof(T)*aNum);
for (int i = 0; i<aNum; i++)
{
T var = read();
if (var == NULL)
{
if (isEof)
{
return readCounter;
}
else
{
perror ("Error Reading File - Insufficient var type");
return -1;
}
}
else
{
*apBuf[i] = var;
readCounter++;
}
}
return readCounter;
}
*apBuf[i] = var;
This is parsed as if it was written:
*(apBuf[i]) = var;
This is obviously not what you want; apBuf is a pointer to a pointer to an array; you are treating it as a pointer to an array and you are dereferencing the ith element of it. What you really mean is:
(*apBuf)[i] = var;
*apBuf gives you "the object pointed to by apBuf," which is the array; then you obtain the ith element of the array.
That said, this is rather unusual: why not accumulate the data into a std::vector<T> and return that from the function? Then you don't have to worry about the explicit dynamic memory management. (Also, is T always a pointer type? If not, then var == NULL makes no sense.)
Well, you used malloc to allocate the array, and then tried to assign to it. This is undefined behaviour, because you have to construct the objects.
Oh, and you should really, really consider using self-owning resource classes, because malloc and this style of programming in general is hideously unsafe. What if T's copy constructor throws an exception? Memory leak. Just for example.
One issue you have is your using malloc instead of new. If T is a class the constructor won't be called.