Convert data from const void *data to double - c++

I received data from some other function to myfunction(const void *data) where pointer data stores the values like {0,0,0,0,0,0,0,40,20,0,0,0,0,0,0}.
I want to access just values from {40,20,0,0,0,0,0,0} and convert into a double type value that should give 8.0 . For accessing and conversion to double type I have tried pointer to double:
double* dptr;
dptr=&(*data+8);
dptr;
that was giving error like
"error: ‘const void*’ is not a pointer-to-object type"

In C you cannot de-reference a void pointer.
So you can type cast the void pointer and use it.
something like this dptr=((double*)data+8); So the data which is void is considered as a double pointer now.

Edit Your post is very unclear. Assuming data is actually a pointer to an array of double the solution is even simpler:
double * pd = static_cast<double const *>(data);
double d0 = pd[0];
double d1 = pd[1];
or (C):
double * pd= (double const *)(data);
double d0 = pd[0];
double d1 = pd[1];
You cannot perform pointer arithmetics and dereferencing on void * so *data or data + 8 are invalid.
I don’t understand exactly what you are trying to do, but here is how you access data in your array:
Assuming the data stored is actually int, to access the 8th element and convert it into double you should write:
double el = static_cast<double>*(static_cast<int const *>(data) + 8));
better yet:
int *p = static_cast<int const *>(data);
double el = static_cast<double>(p[8]);
Please note that is is really important that you convert data to the original pointer type . In my example I used int but you should replace it with what your data actually is.
On that note, if what you are showing as {0,0,0,0,0,0,0,40,20,0,0,0,0,0,0} are actually bytes, then the original pointer type is char * and you should convert to char *.
To clarify furthermore converting data from pointers:
Let’s say you have a pointer to int:
int i = 24;
int *pi = &i;
How would you convert to double the data found on address pi?
// wrong:
double *pd = &i;
cout << *pd << endl;
That is wrong because what you do is converting the pointer type and not the actual data. In effect you interpret the bit pattern found at address pi as a bit pattern representing a double. But that bit pattern represents and int.
What you need to do is retrieve the data as it is: an int and then convert the int to double:
int x = *pi;
double d = (double) x;

#include <stdio.h>
#include <string.h>
double myfunction(const void *data){
double v;
memcpy(&v, data, sizeof(v));
return v;
}
int main (int argc, char *argv[]) {
unsigned char data[] = {0x40,0x20,0,0,0,0,0,0};
int i, len = sizeof(data);
//reverse data If necessary
for(i=0;i<len/2;++i){
unsigned char c = data[i];
data[i] = data[len -1 -i];
data[len -1 -i] = c;
}
double v;
v = myfunction(data);
printf("%f\n", v);//8.000000
return 0;
}

You cannot perform pointer arithmetic in void pointers, since you don't know the size of the inner data (as it says, it is void). You have to typecast it to a type with a known size.
The correct typecasting and pointer arithmetic is as follows (using old C conversions):
char * ptr=(char *)data;
double * myDoublePtr=(double *)(ptr+8);
double myDouble=*myDouble;
Or, as you have two doubles consecutive:
double * ptr=(double *)data;
double myDouble=*(ptr+1); //This will access the second double.
This is because an offset in pointer arithmetics will perform a jump of offset*sizeof(type) bytes, so in a char type, the number of bytes jumped will actually be the same as your offset.

Related

Why does the following result in segmentation fault?

const int* additional(int* s, int* f){
const int* ts = reinterpret_cast<const int*>(*s + *f);
return ts;
}
int main() {
int a = 10, b = 20;
const int* oc = additional(&a, &b);
std::cout << *oc;
return 0;
}
I've tried using static, although it produces the same error
There are many things wrong with your code.
*s + *f is an int, not a pointer (you add the dereferenced values).
you are doing a reinterpret cast which isn't needed at all. Just pass the int's directly without pointers and you are good to go.
const int additional(int s, int f){
return s + f;
}
int main() {
int a = 10, b = 20;
const int oc = additional(a, b);
std::cout << oc;
return 0;
}
You reinterpret the number 30 as a pointer to const int and attempt to read through the reinterpreted pointer. The operating system noticed that the process was attempting to access an address wasn't mapped for the process and sent the segfault signal to terminate the process in order to protect the badly behaving process from itself.
Reinterpret casting is unsafe. Don't use it unless you know what you're doing. And when you know what you're doing, you'll know that it's quite rare to need to use it.
I was aiming to shorten the int t = *f + *s;
That is already extremely short. The function that you defined is much longer and so is even a call to the function. Note that the initialiser expression that you quote has type int while your function returns const int*. That, along with the broken reinterpret cast are the problem.
If you wanted to make the indirection shorter, then how about using references instead of pointers:
const int& f = a;
const int& s = b;
int t = a + b; // shorter

What does `float* const* ` mean?

Take a look at this function signature:
AudioBlock (SampleType *const *channelData, size_t numberOfChannels, size_t startSampleIndex, size_t numberOfSamples)
from here
The main type used if float* so let's think of the signature as
AudioBlock (float *const *channelData, size_t numberOfChannels, size_t startSampleIndex, size_t numberOfSamples)
What does float *const *channelData mean? channelData should be a const pointer to a float pointer? What is a const* something? I don't see the type of the inner pointer.
Suppose I want to create a vector of zeros so I can pass to AudioBlock:
std::vector<float> v(bufferOriginal.getNumChannels()*bufferOriginal.getNumSamples(), 0);
How do I get a float *const *channelData to this vector data?
What does float* const* mean?
float is a fundamental floating point type. T* is a pointer to T. const is a qualifier that applies to whatever is on the left side of it (except when it is the left most token in which case it applies to right). Since both qualifier and the pointer apply to left, it is easies to read from right to left (there are more complicated cases where this simplified rule of thumb is wrong):
float * const * // original
* const * float // reversed
* | const * | float // added spaces and separators
non-const pointer to | const pointer to | non-const float // translated to english
Arrays are an example of more complex cases where just right to left doesn't work. For the more complex rule that works with all compound types, see "clockwise rule" or "spiral rule".
So it's not possible to get a float* const * to the vector data then, right?
You could, if you had a vector like this:
std::vector<float*> vector_of_pointers;
float* const* ptr = vector_of_pointers.data();
You could make element of that vector point to your vector of floats.
vector_of_pointers.push_back(v.data());
This parameter declaration
float *const *channelData
means that the variable channelData (read from tight to left) is a pointer to a constant pointer (the pointer itself that is constant) to a non-constant object of the type float.
To make it more clear consider the following demonstrative program.
#include <stdio.h>
int main(void)
{
float x = 1.1f;
float y = 2.2f;
printf( "x = %f\n", x );
float * const px = &x;
// px = &y; // error: assignment of read-only variable ‘px’
*px = y;
printf( "x = %f\n", x );
float * const * ppx = &px;
// *ppx = &y; // error: assignment of read-only location ‘*ppx’
**ppx = 3.0f;
printf( "x = %f\n", x );
return 0;
}
Its output is
x = 1.100000
x = 2.200000
x = 3.000000
As you can see as the pointer px is a constant variable it has to be initialized when it is declared. You can not change it such a way that it will point to another variable. But you can use pc to change the value of the object pointed to by px. The variable ppx is a pointer to such a pointer.

How to convert a byte array of size 64 to a list of double values in Arduino C++?

void Manager::byteArrayToDoubleArray(byte ch[]) {
int counter = 0;
// temp array to break the byte array into size of 8 and read it
byte temp[64];
// double result values
double res[8];
int index = 0;
int size = (sizeof(ch) / sizeof(*ch));
for (int i = 0; i < size; i++) {
counter++;
temp[i] = ch[i];
if (counter % 8 == 0) {
res[index] = *reinterpret_cast<double * const>(temp);
index++;
counter = 0;
}
}
}
Here result would be a list of double values with count = 8.
Your problem is two things. You have some typos and misunderstanding. And the C++ standard is somewhat broken in this area.
I'll try to fix both.
First, a helper function called laundry_pods. It takes raw memory and "launders" it into an array of a type of your choice, so long as you pick a pod type:
template<class T, std::size_t N>
T* laundry_pods( void* ptr ) {
static_assert( std::is_pod<std::remove_cv_t<T>>{} );
char optimized_away[sizeof(T)*N];
std::memcpy( optimized_away, ptr , sizeof(T)*N );
T* r = ::new( ptr ) T[N];
assert( r == ptr );
std::memcpy( r, optimized_away, sizeof(T)*N );
return r;
}
now simply do
void Manager::byteArrayToDoubleArray(byte ch[]) {
double* pdouble = laundry_pods<double, 8>(ch);
}
and pdouble is a pointer to memory of ch interpreted as an array of 8 doubles. (It is not a copy of it, it interprets those bytes in-place).
While laundry_pods appears to copy the bytes around, both g++ and clang optimize it down into a binary noop. The seeming copying of bytes around is a way to get around aliasing restrictions and object lifetime rules in the C++ standard.
It relies on arrays of pod not having extra bookkeeping overhead (which C++ implementations are free to do; none do that I know of. That is what the non-static assert double-checks), but it returns a pointer to a real honest to goodness array of double. If you want to avoid that assumption, you could instead create each doulbe as a separate object. However, then they aren't an array, and pointer arithmetic over non-arrays is fraught as far as the standard is concerned.
The use of the term "launder" has to do with getting around aliasing and object lifetime requirements. The function does nothing at runtime, but in the C++ abstract machine it takes the memory and converts it into binary identical memory that is now a bunch of doubles.
The trick of doing this kind of "conversion" is to always cast the double* to a char* (or unsigned char or std::byte). Never the other way round.
You should be able to do something like this:
void byteArrayToDoubleArray(byte* in, std::size_t n, double* out)
{
for(auto out_bytes = (byte*) out; n--;)
*out_bytes++ = *in++;
}
// ...
byte ch[64];
// .. fill ch with double data somehow
double res[8];
byteArrayToDoubleArray(ch, 64, res);
Assuming that type byte is an alias of char or unsigned char or std::byte.
I am not completly sure what you are trying to achieve here because of the code (sizeof(ch) / sizeof(*ch)) which does not make sense for an array of undefined size.
If you have a byte-Array (POD data type; something like a typedef char byte;) then this most simple solution would be a reinterpret_cast:
double *result = reinterpret_cast<double*>(ch);
This allows you to use result[0]..result[7] as long as ch[] is valid and contains at least 64 bytes. Be aware that this construct does not generate code. It tells the compiler that result[0] corresponds to ch[0..7] and so on. An access to result[] will result in an access to ch[].
But you have to know the number of elements in ch[] to calculate the number of valid double elements in result.
If you need a copy (because - for example - the ch[] is a temporary array) you could use
std::vector<double> result(reinterpret_cast<double*>(ch), reinterpret_cast<double*>(ch) + itemsInCh * sizeof(*ch) / sizeof(double));
So if ch[] is an array with 64 items and a byte is really an 8-bit value, then
std::vector<double> result(reinterpret_cast<double*>(ch), reinterpet_cast<double*>(ch) + 8);
will provide a std::vector containing 8 double values.
There is another possible method using a union:
union ByteToDouble
{
byte b[64];
double d[8];
} byteToDouble;
the 8 double values will occupie the same memory as the 64 byte values. So you can write the byte values to byteToDouble.b[] and read the resultingdouble values from byteToDouble.d[].

What is the int* here?

So I know that a pointer is:
int *someNumber;
but I have run accross some code with:
int* pOutputData = nullptr;
byte* pOutputDataByte = nullptr;
What does int* mean?
Is that some kind of array of int? Is it a pointer to the type?
int * and int* are the same thing. The whitespace doesn't change anything.
int * can be used either as a pointer to int or as a pointer to the first element of an array of ints. How a variable is used is context-dependent. Judging by the variable names, I'd guess that someNumber points to a single int and pOutputData points to an array.
Both are same
White space does not mean anything in c
int * num ;
int *num;
int* num;
All the above statements are same!
We use int* as default; mainly in data structure, to avoid confusion.
Always read pointer variables from right to left
int *p means p is a pointer to an int
char *p means p is a pointer to a char
const int *p means p is a pointer to an integer constant
int * const p means p is constant pointer to an int

Error: invalid operands of types 'int' and 'float*' to binary operator '/'

Error: invalid operands of types 'int' and 'float*' to binary'operator/'
int *average = new int((num) / data);
showing up for this line of code.
Why so?
float *data;
int num;
int mode;
double average, median;
cout << "How many students were surveyed? ";
cin >> num;
data = makeArray(num);
float getAverage(float *data, int num)
{
int *average = new int((data) / num);
return *average;
}
It means you are comparing two incompatible types together. One of num and data is an int, and the other is a float*. Depending upon the behavior you want you will want to
Dereference the pointer, as in *x for whichever x is the pointer
2a. You will want to cast the int to a float for floating point division, where result is converted back to an int
2b. You will want to cast the float to an int, for integer division, which will then be converted back to an int.
Update
Since you updated your code I'll point out a bigger problem; you are now leaking memory.
I would suggest you consider instead returning your integer by value and potentially pass by reference or constant reference and avoid pointers entirely here, but more over I would suggest some symmetry in your input parameters as well as const correctness:
//your code:
float getAverage( float *data, int sum )
{
//data is a float* and needs to be de-ref'd and casted to int for float but isnt
int *average = new int( (data) / num );
//note that now average is a pointer to a newly constructed int that will never be free'd
return *average; //because you return it here, where the value will then be implicily converted to a float and be mostly worthless.
}
// In both suggestions I will use symmetric types, I will not introduce dynamic memory and I will use floating point division for maximal accuracy.
// Suggestion one use Const References
float getAverage( const float &data, const int &num)
{
float result = data / (float) num;
return result;
}
// Suggestion two use pointers to constants
float getAverage( const float *data, const int *num )
{
float result = (*data) / float(*num);
return result;
}
// Suggestion three pass by value since primitives are cheap
float getAverage( float data, int num)
{
float result = data / (float) num;
return result;
}