Return dynamic array in C++ - c++

I need to return a unsigned int* from a function. The code below will compile but will crash at run time on a Windows 64 bit machine. I know I am making a silly mistake somewhere and can someone point it out for me. :p. I also have declared the function in my header, so I know its not that error.
Please note I have censored the variable names and numbers because the problem in which this function resides is not for public release yet.
Function:
unsigned int* convertTime(unsigned int inputInteger, unsigned short inputFrac) {
unsigned int* output = new unsigned int[2];
double messageTimeFraction = double(inputFrac) * 20e-6;
output[1] = unsigned int(inputInteger + 2209032000);
output[2] = unsigned int(messageTimeFraction * 2e32);
return output; // Seconds
}
Implementation:
unsigned int* timeStamp;
timeStamp = convertTime(inputInteger,inputFrac);

Well, for starters you have output[1] and output[2]. Arrays are zero-indexed in c/c++, so these should be: output[0] and output[1].
But, since you're asking about c++... I urge you to use std::vector or std::pair.
(Of course, for readability's sake, you might just want to use a trivial struct with useful field names)

I know I am making a silly mistake
somewhere and can someone point it out
for me
Sure, and it has nothing to do with the Q's subject:
output[2] = unsigned int(inputFrac * 2e32);
The correct entries in output are [0] and [1] -- you're indexing out of bounds. "Undefined behavior" results (such as, the crash you observe).

The indexes in an array of 2 elements are array[0] and array[1], so change it to:
output[0] = unsigned int(inputInteger + 2209032000);
output[1] = unsigned int(inputFrac * 2e32);

use output[0] and output[1], C / C++ arrays are 0 - based

Arrays in C++ are zero based, so the elements of your array of size two are output[0] and output[1]
You also might want to return something that better represents the data you are returning, such as a struct with seconds and fractional_seconds members rather than creating a new array.
It's also somewhat strange what you are doing -- 2209032000 is the number of seconds in 70 years, and the result of multiplying a short by 2e32 will overflow the size of unsigned int.

The more usual way to write functions like this in a C style is to pass in the reference to the variable that will be set.
As a convenience you return the output buffer so that the function can easily be used in an expression.
unsigned int* convertTime(unsigned int* output, unsigned int inputInteger, unsigned short inputFrac) {
double messageTimeFraction = double(inputFrac) * 20e-6;
output[0] = unsigned int(inputInteger + 2209032000);
output[1] = unsigned int(inputFrac * 2e32);
return output; // Seconds
}
// later
unsigned int seconds[2];
unsigned int* pseconds;
pseconds = convertTime(seconds,a,b);

I created a time structure for the various formats and wrote converter functions to handle the conversions. By using structures, I do not have to worry about memory leaks and improved readability. Furthermore the code is now more scalable than using dynamic arrays, as I can add more fields and create new time formats.
struct time{
unsigned int timeInteger;
unsigned int timeFraction;
}time_X, time_Y;
My silly mistake was the typo of zero-based indexing but the bigger mistake was using dynamic array.

Related

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[].

Why can it still compile/run after changing locations of different parameters with different types?

Last night I spent 1 hour to debug. I was writing a program of Huffman_coding. Part of my wrong code is blow:
class HTree
{
public:
HTree* left;
HTree* right;
int weight;
char ch;
HTree(){left = right = NULL; ch = '\0'; weight = 0;}
HTree(HTree* l, HTree* r, char c, int w){left = l; right = r; ch = c; weight = w;}
~HTree(){delete left; delete right;}
bool ISleaf(){return !left && !right;}
};
And this is one piece of code in HTree* BuildTree(int* frequency):
QTree.push(new HTree(NULL, NULL, frequency[i], (char)i));
As can be see, the order of these two parameters is inverse - char c, int w and frequency[i], (char)i. I didn't realize this little mistake at the beginning. The output is, of course, wrong.
But my question is, why can it still compile? or why can it still run? Because the answer/cout is totally wrong. And according to the different types, I think it cannot compile successfully - char != int, am I right?
Can anyone tell me why does this happen? Does it automatically converse the int to char and char to int, and then it can compile and run, and got a wrong answer?
Well, let me specify more clearly, my main question is not whether it can automatically converse or not, it's why my answer is wrong if the converse can automatically happen.
The wrong output:
The right output:
Thanks in advance!
C++ can convert chars (that are 8 bit integers) to int using implicit casting, if the target type is wider than the source type, which is the case here (int is usually 16 or 32 bits wide depending on the platform, char is 8 bit).
When assigning an int to a char, the compiler usually prints a warning message (but the assignment will work).
Yes, there are implicit conversions from char to int and from int to char.
It is wrong because instead of frequency you initialize your every HTree object with some i value. And the c member is initialized with frequency. So because of casting your code is gonna compile and work, and produce wrong results all the way.

C++ static_cast from int* to void* to char* - can you help me to understand this code?

I'm a beginner in C++, and I have problem with understanding some code.
I had an exercise to do, to write function which returns size of int, and do not use sizeof() and reinterpret_cast. Someone gave me solution, but I do not understand how it works. Can you please help me to understand it? This is the code:
int intSize() {
int intArray[10];
int * intPtr1;
int * intPtr2;
intPtr1 = &intArray[1];
intPtr2 = &intArray[2];
//Why cast int pointer to void pointer?
void* voidPtr1 = static_cast<void*>(intPtr1);
//why cast void pointer to char pointer?
char* charPtr1 = static_cast<char*>(voidPtr1);
void* voidPtr2 = static_cast<void*>(intPtr2);
char* charPtr2 = static_cast<char*>(voidPtr2);
//when I try to print 'charPtr1' there is nothing printed
//when try to print charPtr2 - charPtr1, there is correct value shown - 4, why?
return charPtr2 - charPtr1;
}
To summarize what I don't understand is, why we have to change int* to void* and then to char* to do this task? And why we have the result when we subtract charPtr2 and charPtr1, but there is nothing shown when try to print only charPtr1?
First of all, never do this in real-world code. You will blow off your leg, look like an idiot and all the cool kids will laugh at you.
That being said, here's how it works:
The basic idea is that the size of an int is equal to the offset between two elements in an int array in bytes. Ints in an array are tightly packed, so the beginning of the second int comes right after the end of the first one:
int* intPtr1 = &intArray[0];
int* intPtr2 = &intArray[1];
The problem here is that when subtracting two int pointers, you won't get the difference in bytes, but the difference in ints. So intPtr2 - intPtr1 is 1, because they are 1 int apart.
But we are in C++, so we can cast pointers to anything! So instead of using int pointers, we copy the value to char pointers, which are 1 byte in size (at least on most platforms).
char* charPtr1 = reinterpret_cast<char*>(intPtr1);
char* charPtr2 = reinterpret_cast<char*>(intPtr2);
The difference charPtr2 - charPtr1 is the size in bytes. The pointers still point to the same location as before (i.e. the start of the second and first int in the array), but the difference will now be calculated in sizes of char, not in sizes of int.
Since the exercise did not allow reinterpret_cast you will have to resort to another trick. You cannot static_cast from int* to char* directly. This is C++'s way of protecting you from doing something stupid. The trick is to cast to void* first. You can static_cast any pointer type to void* and from void* to any pointer type.
This is the important bit:
intPtr1 = &intArray[1];
intPtr2 = &intArray[2];
This creates two pointers to adjacent ints in the array. The distance between these two pointers is the size of an integer that you're trying to retrieve. However the way that pointer arithmetic works is that if you subtract these two then the compiler will return you the size in terms of ints, which will always be 1.
So what you're doing next is re-casting these as character pointers. Characters are (or de-facto are) 1 byte each, so the difference between these two pointers as character pointers will give you an answer in bytes. That's why you're casting to character pointers and subtracting.
As for via void* - this is to avoid having to use reinterpret_cast. You're not allowed to cast directly from a int* to a char* with static_cast<>, but going via void* removes this restriction since the compiler no longer knows it started with an int*. You could also just use a C-style cast instead, (char*)(intPtr1).
"do not use sizeof() and reinterpret_cast"... nothing's said about std::numeric_limits, so you could do it like that :)
#include <limits>
int intSize()
{
// digits returns non-sign bits, so add 1 and divide by 8 (bits in a byte)
return (std::numeric_limits<int>::digits+1)/8;
}
Pointer subtraction in C++ gives the number of elements between
the pointed to objects. In other words, intPtr2 - intPtr1
would return the number of int between these two pointers.
The program wants to know the number of bytes (char), so it
converts the int* to char*. Apparently, the author doesn't
want to use reinterpret_cast either. And static_cast will
not allow a direct convertion from int* to char*, so he
goes through void* (which is allowed).
Having said all that: judging from the name of the function and
how the pointers are actually initialized, a much simpler
implementation of this would be:
int
intSize()
{
return sizeof( int );
}
There is actually no need to convert to void*, other than avoiding reinterpret_cast.
Converting from a pointer-to-int to a pointer-to-char can be done in one step with a reinterpret_cast, or a C-style cast (which, by the standard, ends up doing a reinterpret_cast). You could do a C-style cast directly, but as that (by the standard) is a reinterpret_cast in that context, you'd violate the requirements. Very tricky!
However, you can convert from an int* to a char* through the void* intermediary using only static_cast. This is a small hole in the C++ type system -- you are doing a two-step reinterpret_cast without ever calling it -- because void* conversion is given special permission to be done via static_cast.
So all of the void* stuff is just to avoid the reinterpret_cast requirement, and would be silly to do in real code -- being aware you can do it might help understanding when someone did it accidentally in code (ie, your int* appears to be pointing at a string: how did that happen? Well, someone must have gone through a hole in the type system. Either a C-style cast (and hence a reinterpret_cast), or it must have round-tripped through void* via static_cast).
If we ignore that gymnastics, we now have an array of int. We take pointers to adjacent elements. In C++, arrays are packed, with the difference between adjacent elements equal to the sizeof the elements.
We then convert those pointers to pointers-to-char, because we know (by the standard) that sizeof(char)==1. We subtract these char pointers, as that tells us how many multiples-of-sizeof(char) there are between them (if we subtract int pointers, we get how many multiples-of-sizeof(int) there are between them), which ends up being the size of the int.
If we try to print charPtr1 through std::cout, std::cout assumes that our char* is a pointer-to-\0-terminated-buffer-of-char, due to C/C++ convention. The first char pointed to is \0, so std::cout prints nothing. If we wanted to print the pointer value of the char*, we'd have to cast it to something like void* (maybe via static_cast<void*>(p)).
Please read this: richly commented.
int intSize()
{
int intArray[2]; // Allocate two elements. We don't need any more than that.
/*intPtr1 and intPtr2 point to the addresses of the zeroth and first array elements*/
int* intPtr1 = &intArray[0]; // Arrays in C++ are zero based
int* intPtr2 = &intArray[1];
/*Note that intPtr2 - intPtr1 measures the distance in memory
between the array elements in units of int*/
/*What we want to do is measure that distance in units of char;
i.e. in bytes since once char is one byte*/
/*The trick is to cast from int* to char*. In c++ you need to
do this via void* if you are not allowed to use reinterpret_cast*/
void* voidPtr1 = static_cast<void*>(intPtr1);
char* charPtr1 = static_cast<char*>(voidPtr1);
void* voidPtr2 = static_cast<void*>(intPtr2);
char* charPtr2 = static_cast<char*>(voidPtr2);
/*The distance in memory will now be measure in units of char;
that's how pointer arithmetic works*/
/*Since the original array is a contiguous memory block, the
distance will be the size of each element, i.e. sizeof(int) */
return charPtr2 - charPtr1;
}

Assigning an array variable to a pointer of same data type in C++

IN the following C++ snippet, is a=b assigment possible ??:
unsigned int * a;
D3DCOLOR b[16];
a=(unsigned int)b;
Will this assignment copy all the elements of b array to a? Is the typecast fine?
First of all, it should have been:
a = (unsigned int *)b; // note the *
More importantly, this just makes a point to contents of b, and it does not copy it. If you want to copy arrays, you have to do it explicitly, for example with a for loop or std::copy, that is if you don't want to go with classes and stuff.
Side note: to copy into a, you need memory for a! You can do it either on the stack:
unsigned int a[16]; // 16 is an example
or dynamically (for example with new).
Your code will not work, with a pointer you get access to the same memory as the object you point it to.
What do you want to do, exactly? From your code, I'd guess that the array you have is a bit array and you want the corresponding unsigned integer.
In that case, do something like this:
unsigned int a;
unsigned int length = 16;
D3DCOLOR b[length];
for(int i = 0; i < length; i++)
{
a |= b[(length-1) - i] << i;
}
This will take each bit, shift it by the requisite amount and then write it to a. Take a look at bit operations in c / c++ if you want to know more.
(Note: This code assumes big endian bit order).

Cast int as byte array in C++

I am trying to use implement the LSB lookup method suggested by Andrew Grant in an answer to this question: Position of least significant bit that is set
However, it's resulting in a segmentation fault. Here is a small program demonstrating the problem:
#include <iostream>
typedef unsigned char Byte;
int main()
{
int value = 300;
Byte* byteArray = (Byte*)value;
if (byteArray[0] > 0)
{
std::cout<< "This line is never reached. Trying to access the array index results in a seg-fault." << std::endl;
}
return 0;
}
What am I doing wrong?
I've read that it's not good practice to use 'C-Style' casts in C++. Should I use reinterpret_cast<Byte*>(value) instead? This still results in a segmentation fault, though.
Use this:
(Byte*) &value;
You don't want a pointer to address 300, you want a pointer to where 300 is stored. So, you use the address-of operator & to get the address of value.
While Erik answered your overall question, as a followup I would say emphatically -- yes, reinterpret_cast should be used rather than a C-style cast.
Byte* byteArray = reinterpret_cast<Byte*>(&value);
The line should be:
Byte* byteArray = (Byte*)&value;
You should not have to put the (void *) in front of it.
-Chert
char *array=(char*)(void*)&value;
Basically you take a pointer to the beginning of the string and recast it to a pointer to a byte.
#Erik already fixed your primary problem, but there is a subtle one that you still have. If you are only looking for the least significant bit, there is no need to bother with the cast at all.
int main()
{
int value = 300;
if (value & 0x00000001)
{
std::cout<< "LSB is set" << std::endl;
}
return 0;
}