store double pointer address and retrieve its value - c++

I am trying to store the memory address in a double pointer and cout the value at that memory address but getting errors.
below is the code i am trying to compile:
struct doubleValue{
double a;
};
int main(){
doubleValue *DBL = new doubleValue;
DBL->a=15;
// now I want to store the address of DBL->a in a double pointer and print out the value of double pointer.
double &doubelPtr = &DBL->a;
cout<< *doubelPtr; // this value should be 15
}
If I run the above code then I get a compiler error "error: invalid initialization of non-const reference of type 'double&' from an rvalue of type 'double*'
double &doubelPtr = &DBL->a;
^"
Can somebody help me to correct this code? Thanks!

You are erroneously using the reference operator here:
double &doubelPtr = &DBL->a;
You should just declare a pointer and assign the address to it.
double *doubelPtr = &DBL->a;
The above uses the address-of operator. I know it's confusing that both operators (reference and address) use the same symbol &, but that's how it is.
However, I'm curious as to why you need to do this? Is it because you're calling a function that requires a pointer to double? If so, there is no need to do the roundabout way of declaring a pointer to double and assigning to it. Just pass the address of the double to the function.

double &doubelPtr should be double *doubelPtr

This is a case of reference vs. pointer;
double &doublePtr
is a reference, not an address; try doing this with
double *doublePtr

Related

Why doesn't it let me to initialize like this? [duplicate]

I'm trying to send value into function using reference pointer but it gave me a completely non-obvious error
#include "stdafx.h"
#include <iostream>
using namespace std;
void test(float *&x){
*x = 1000;
}
int main(){
float nKByte = 100.0;
test(&nKByte);
cout << nKByte << " megabytes" << endl;
cin.get();
}
Error : initial value of reference to non-const must be an lvalue
I have no idea what I must do to repair above code, can someone give me some ideas on how to fix that code?
When you pass a pointer by a non-const reference, you are telling the compiler that you are going to modify that pointer's value. Your code does not do that, but the compiler thinks that it does, or plans to do it in the future.
To fix this error, either declare x constant
// This tells the compiler that you are not planning to modify the pointer
// passed by reference
void test(float * const &x){
*x = 1000;
}
or make a variable to which you assign a pointer to nKByte before calling test:
float nKByte = 100.0;
// If "test()" decides to modify `x`, the modification will be reflected in nKBytePtr
float *nKBytePtr = &nKByte;
test(nKBytePtr);
The &nKByte creates a temporary value, which cannot be bound to a reference to non-const.
You could change void test(float *&x) to void test(float * const &x) or you could just drop the pointer altogether and use void test(float &x); /*...*/ test(nKByte);.
When you call test with &nKByte, the address-of operator creates a temporary value, and you can't normally have references to temporary values because they are, well, temporary.
Either do not use a reference for the argument, or better yet don't use a pointer.
Simply replace test(&nKByte); with test(nKByte); in main function
Simply, initializers of references are expected to be objects not their addresses, but if you need to assign a reference to otherwise (like your code above), declare this reference as const. Why const? because if not, the compiler does think that you need to, later on, modify the pointer itself not what it's pointing to.

Why can the compiler not differentiate between double** and double*

I have created two routines, one to sort a vector in-place:
void Sort(double** vector, unsigned int vectorLength) {
//...
}
and one that returns a new array with the sorted result:
double* Sort(double* vector, unsigned int vectorLength) {
//...
}
Later using the sort method:
double* test = new double[5];
//...
Sort(*test, 5);
I receive the compiler error that 'none of the 2 overloads could convert all the argument types.'
Is not the type double*, a pointer to a double, not fundamentally different to a double**, a pointer to a pointer to a double?
How is this not clear to the compiler?
You get the error because *test expression is neither double* nor double** - it's a double, with no asterisks.
Passing test without dereferencing it would have worked:
double* sorted = Sort(test, 5); // Invokes the second overload
Note that you can sort in place even if you pass a pointer. Using an overload for this that requires an artificial &, works but it makes your API counter-intuitive.
A better approach would be defining a method with the same set of parameters, but a different name, for example
double* Sort(double* vector, size_t vectorLength) {
//...
}
void SortInPlace(double* vector, size_t vectorLength) {
//...
}
Your variable test has type double* and so *double has type double. Which means that you are attempting to pass double which matches neither double* nor double**.
One possibility is that you actually meant to create a sorted copy of the original array:
double* sorted = Sort(test, 5);
But I rather presume, since your call to Sort ignores the return value, that you meant to pass &test to sort in-place.
Sort(&test, 5);
However, that in itself indicates that your interface is badly designed. You would pass &test if you wanted the function to modify test. But you don't. You want the function to modify the array that test refers to. Your in-place sort function can, and should, be implemented by passing a parameter of type double*.
It is my opinion that you are abusing function overloading here. I would recommend that you choose a different design. I would use functions with different names.
Some other comments:
Use size_t for array lengths.
Use const to indicate that an input parameter shall not be modified.
It's very clear, but the expression *test when test has the type double * is the same as test[0], i.e. it's a double and not a pointer at all.
Perhaps you meant &test to take the address of the pointer.
*test goes directly to the value stored in that memory address. So, it goes to the double stored in the address test, which is a pointer to double.
So, you're passing a double value, not a pointer.
Your work would work with either of these two:
Sort(test, 5); // Passes a pointer to double.
or
Sort(&test, 5); // Gives you the address of test. Passes a pointer to a pointer to double.

Casting with pointer C++

Say I have an object:
void *tmpValue;
and say I know that tmpValue points to a double.
A way to cast this into a double is to do the following:
double* dblPtr = (double*) tmpValue;
double dbl = *dblPtr;
But why does a direct casting from void* to double not work?
double dbl = (double) tmpValue; //error: "cannot convert from 'void*' to 'double'
Thanks in advance.
Interpreting a pointer (a memory address) as a floating-point value is not a sensible operation, and it probably fails on your platform because void * and double are not even the same size.
What you want to do is interpret the pointer as double * and dereference that double * pointer, as in your second code snippet.
You can do this in one line:
double dbl = *(double *)tmpValue;
But, hey, this is C++. Better to do
double dbl = *static_cast<double *>(tmpValue);
You can't cast from a pointer type to double. Recall that pointer type is essentially a memory address (typically 4 bytes containing location information of the data on the memory). Hence you can cast pointer type to integer, but casting to double wouldn't make sense.
When you cast the void* pointer into double* pointer type, you are essentially saying "this is now an address of a double rather than an address of void*"
If you want to get the value as double in one liner nevertheless, you can do
double dbl = *( (double*) tmpValue );
double dbl = *(double*)tmpValue
dereference the pointer and cast ist value

Difference between & and * as a parameter

What is the difference between the following two parameter types? The first accepts a pointer, which is in effect a memory address, and the second is also a memory address?
foo(float& bar)
{
// do stuff
}
foo(float* bar)
{
// do stuff
}
Could you not call both with:
float pow = 3.0f;
foo(&pow);
or
float* pow = 3.0f;
foo(pow);
A pointer can be NULL, while a reference can't. This can be useful if you need to pass a NULL object for whatever reason.
With the pointer syntax, you pass a pointer when you call the function. With references, you just pass the variable:
refer(float& bar) {}
point(float* bar) {}
float afloat = 1.0f;
refer(afloat);
point(&afloat);
This means with the pointer syntax you have to pass a pointer when you call the function. With the reference syntax, you don't know if the function takes it by reference or by value without looking at the function definition.
With the reference syntax you don't have to dereference the pointer in your function, and work with it more naturally in your // do stuff section.
foo(float& bar)
{
bar = 3.0f;
}
// versus
foo(float* bar)
{
*bar = 3.0f;
}
No, they are not the same. The first is taking a parameter by reference and would be called like this:
float pow = 3.0f;
foo(pow) // foo can change the value of pow!
the second accepts a pointer and could be called by either of your examples (both of which are passing a pointer, not a reference).
NOTE: your second example, while it passes a float* does not properly initialize the pow variale, and therefore won't compile. Instead, something like this would work:
float *pow = new float(3.0);
foo(pow);
delete pow;
While references have similarities to pointers, it is not mandated that they are implemented internally by pointers. For example, often the compiler can inline calls and just modify the argument directly, no pointer passed in that case.
In general, think of a reference as "just another name" for a variable. For example:
Person Samuel_Clemens;
Person &Mark_Twain(Samuel_Clemens); // just another name
The difference is that the first cannot receive a null pointer, while the second can.
But with a bit of effort you can make the first receive null pointer too:
float *a = null;
pow(*a);
Edit: All the following proved to be wrong, I'll keep it as reference for the comments:
The difference is that the reference version will throw an exception when dereferencing a null reference while pointer version will just segfault:
float *a = null;
float &b = *a; // works... somehow?
b = 1; // throws exception
*a = 1; // segmentation fault
float* is a pointer to a float number, whereas float& is a reference to a float number.
With a pointer, you can say function(null) letting the argument point to null (which represents nothing in particular, and often causes undefined behaviour (=crash)). A reference can't reference to nothing (at least not that easy).
When using float*, you will always treat this argument as a pointer, and the compiler does as well. When you use float&, you can treat it as a "normal" (i.e. non-pointer) variable, but it is as if you were using a pointer.
In the first (reference), you are interested on reading and writing the original variable. In the secondth (pointer), you are interested on receiving the address of the original variable.
The difference is mostly taste, except the fact that the pointer version allows you to not-pass any value using a NULL value.

what's a variable with & -> double&

So I have a class made in c++ and need to convert it into vb.net but I got problem converting a certain part of a function.
void deg_min_sec2decimal(double deg, double min, double sec, double& dec_deg)
{
dec_deg = (deg+min/60.0+sec/3600.0);
}
What type of variable is "double&", I know a double but what's with the "&"?
It isn't " double &dec_deg" so it isn't an adres (pointers ect.)?
and how would i convert that to vb.net?
Grtz
It's a reference. That means that whatever you set the value to inside the function, the original variable that was passed in from outside will have that value.
You can convert this to VB by using ByRef or making the function return the result of that expression instead of taking the double&, and setting the variable you would have passed in to the result of the function.
So if you had this before:
double retval;
deg_min_sec2decimal(something, something2, something3, retval);
You'd change that to
Dim retval = deg_min_sec2decimal(something, something2, something3)
(I don't know VB so that syntax might be wrong, but you get the idea.)
I'd go with the latter because returning things through arguments is usually only used when you need more than one return value, and that function isn't even returning anything.
double& is just a double passed by reference. In VB.NET, it would be declared ByRef dec_deg as Double.
EDIT: However, I would recommend instead of using a void function to set a value by reference, just change the return type to double and return the expression instead of having to pass a variable by reference.
double& is a reference to a double. This means in that case that the function can change the value of the passed parameter.
In VB, you do this by ByRef parameters:
Sub deg_min_sec2decimal(deg as Double, min as Double, sec as Double, ByRef dec_deg as Double)
Yes, it is an address ("reference" is the correct C++ term). It doesn't matter if the '&' is on the left or the right, C++ doesn't care about whitespace.
double& d; // Same as...
double &d;
Yes, it's an address, but the terminology is a reference. Meaning, what you do to the parameter will effect the variable passed to it. In VB, the equivilant is the ByRef word:
sub someFunc(ByRef someVar as double)