How to idiomatically convert ``char*`` to ``double*`` - c++

I'm relearning C++, and I'm trying to work with boost::iostreams::mapped_file. This class maps file data to char*, I'd like to cast it to double* (since I'm working with doubles).
I could cast it using C-style cast: double* foo = (double*) data, but I'm trying go use idiomatic C++, and C++ favours C++ casts like: static_cast and so on.
I came up with:
double* data = static_cast<double*>((void*)file.data());
(file->data returns char*).
Which really isnt cleaner.
Here is what I'm trying to do (this code works!):
BOOST_AUTO_TEST_CASE(OpenMMapArray){
typedef boost::multi_array_ref<double, 3> arrayd3;
typedef std::array<size_t, 3> index3d;
index3d shape = {{ 20, 20, 20 }};
size_t size = sizeof(double)*std::accumulate(shape.begin(), shape.end(), 1, std::multiplies<size_t>());
boost::iostreams::mapped_file file;
boost::iostreams::mapped_file_params params;
params.path = "/tmp/mmaptest-2";
params.mode = std::ios::in | std::ios::out;
params.new_file_size = size;
file.open(params);
double* data = static_cast<double*>((void*)file.data());
arrayd3 array(data, shape);
array[0][0][0] = 20;
array[0][1][0] = 19;
array[1][0][0] = 18;
array[0][0][5] = 17;
BOOST_CHECK(data[0] == 20);
BOOST_CHECK(data[20] == 19);
BOOST_CHECK(data[20*20] == 18);
BOOST_CHECK(data[5] == 17);
file.close();
}

In this particular case, you actually are trying to re-interpret the data as a different type. So a reinterpret_cast is in order:
double* data = reinterpret_cast<double*>(file.data());

Related

What is happening in this code? reinterpret_cast<int*>(buf)

It seems to me that the buffer is being modified. Does it put 6 integers and then 5 floats into the buffer? It's also strange that they set size to 44 instead of 1024*sizeof(char). Perhaps the whole buffer is passed to write() but write() writes only the first 44 bytes to the client.
Could you please explain line by line? I have no experience with c++.
char buf[1024];
int* pInt = reinterpret_cast<int*>(buf);
*pInt = 5;
*(pInt+1) = 2;
*(pInt+2) = 3;
*(pInt+3) = 4;
*(pInt+4) = 5;
*(pInt+5) = 6;
float* pFloat = reinterpret_cast<float*>(pInt+6);
*pFloat = 111;
*(pFloat+1) = 222;
*(pFloat+2) = 333;
*(pFloat+3) = 444;
*(pFloat+4) = 555;
int n;
int size = (1+2*5)*4;
n = write(buf, size);
Does it put 6 integers and then 5 floats into the buffer?
Yes.
It's also strange that they set size to 11 instead of 1024*sizeof(char)
They don't want to write the entire buffer. Thy want to write just the ints and floats that were written to the buffer.
FWIW, that is poorly written code. It assumes that sizeof(int) and sizeof(float) are both equal to 4. A more portable method would use:
int size = 6*sizeof(int) + 5*sizeof(float);
Caution
Even though the posted code might work under some, perhaps most, circumstances, use of
int* pInt = reinterpret_cast<int*>(buf);
*pInt = 5;
is cause for undefined behavior by the standard. It violates the strict aliasing rule. There wasn't an int to begin with at that location.
Had you used:
int array[5] = {};
char* cp = reinterpret_cast<char*>(array);
// ...
int* iptr = reinterpret_cast<int*>(cp);
*iptr = 10;
there would be no problem since cp points to a place where an int was there to begin with.
For your use case, it will be better to use:
char buf[1024];
int intArray[] = {5, 2, 3, 4, 5, 6};
std::memcpy(buff, intArray, sizeof(intArray));
float floatArray = {111, 222, 333, 444, 555};
std::memcpy(buff+sizeof(intArray), floatArray, sizeof(floatArray));
int n;
int size = sizeof(intArray) + sizeof(floatArray);
n = write(buf, size);
Further reading:
reinterpret_cast creating a trivially default-constructible object
Unions and type-punning

Access violation, cant figure out the reason

So, been building this class:
public class BitArray {
public:
unsigned char* Data;
UInt64 BitLen;
UInt64 ByteLen;
private:
void SetLen(UInt64 BitLen) {
this->BitLen = BitLen;
ByteLen = (BitLen + 7) / 8;
Data = new unsigned char(ByteLen + 1);
Data[ByteLen] = 0;
}
public:
BitArray(UInt64 BitLen) {
SetLen(BitLen);
}
BitArray(unsigned char* Data, UInt64 BitLen) {
SetLen(BitLen);
memcpy(this->Data, Data, ByteLen);
}
unsigned char GetByte(UInt64 BitStart) {
UInt64 ByteStart = BitStart / 8;
unsigned char BitsLow = (BitStart - ByteStart * 8);
unsigned char BitsHigh = 8 - BitsLow;
unsigned char high = (Data[ByteStart] & ((1 << BitsHigh) - 1)) << BitsLow;
unsigned char low = (Data[ByteStart + 1] >> BitsHigh) & ((1 << BitsLow) - 1);
return high | low;
}
BitArray* SubArray(UInt64 BitStart, UInt64 BitLen) {
BitArray* ret = new BitArray(BitLen);
UInt64 rc = 0;
for (UInt64 i = BitStart; i < BitLen; i += 8) {
ret->Data[rc] = GetByte(i);
rc++;
}
Data[rc - 1] ^= (1 << (BitLen - ret->ByteLen * 8)) - 1;
return ret;
}
};
just finished writing the SubArray function and went on to test but I get "Access violation: attempted to read protected memory" on the line where GetByte(i) gets called. I tested a bit and it doesn't seem to have anything to do with the data array or i, placing "int derp = GetByte(0)" on the first line of the function produces the same error.
calling GetByte from outside the class works fine, I don't understand whats going on.
the test function looks like this:
unsigned char test[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
BitArray* juku = new BitArray(test, 64);
auto banana = juku->GetByte(7); //this works fine
auto pie = juku->SubArray(7, 8);
You might want to consider creating an array of characters, changing:
Data = new unsigned char(ByteLen + 1);
into:
Data = new unsigned char[ByteLen + 1];
In the former, the value inside the parentheses is not the desired length, it's the value that *Data gets initialised to. If you use 65 (in an ASCII system), the first character becomes A.
Having said that, C++ already has a pretty efficient std::bitset for exactly the situation you seem to be in. If your intent is to learn how to make classes, by all means write your own. However, if you want to just make your life simple, you may want to consider using the facilities already provided rather than rolling your own.

ctypes: Initialize array of arrays and pass to C function

I've been fooling with ctypes and have come across two problems:
Problem 1. I would like to build a cellComplex using double* arrays, but I want new_cellComplex to accept an array of double*'s (along with a size_t argument) rather than a fixed number of double*'s. With a fixed number the code looks like this (and it runs fine):
extern "C" {
void * new_cellComplex(double* p_x, double* p_y, double* p_z) {
std::vector< std::pair<double,double> > point;
point.push_back( std::make_pair(p_x[0],p_x[1]));
point.push_back( std::make_pair(p_x[0],p_x[1]));
point.push_back( std::make_pair(p_x[0],p_x[1]));
cellComplex<double>* cmplx = new cellComplex<double>(point);
return cmplx;
}
with Python code:
import ctypes
cellComplex_lib = ctypes.cdll.LoadLibrary('./cellComplex_lib.so')
cellComplex_lib.new_cellComplex.restype = ctypes.c_void_p
cellComplex_lib.new_cellComplex.argtypes = [ctypes.c_double*2,
ctypes.c_double*2,
ctypes.c_double*2]
p_x = (ctypes.c_double*2)(0.0,1.0)
p_y = (ctypes.c_double*2)(0.0,1.0)
p_z = (ctypes.c_double*2)(0.0,1.0)
cmplx = cellComplex_lib.new_cellComplex(p_x,p_y,p_z)
I would rather have the following (which segfaults):
extern "C" {
void * new_cellComplex(double** p, size_t dim) {
std::vector< std::pair<double,double> > point;
for (size_t i=0; i<dim; ++i) {
point.push_back( std::make_pair(p[i][0],p[i][1]));
}
cellComplex<double>* cmplx = new cellComplex<double>(point);
return cmplx;
}
}
With Python code:
import ctypes
dim = 3
cellComplex_lib = ctypes.cdll.LoadLibrary('./cellComplex_lib.so')
cellComplex_lib.new_cellComplex.restype = ctypes.c_void_p
cellComplex_lib.new_cellComplex.argtypes = [(ctypes.c_double*2)*dim,
ctypes.c_size_t]
p_x = (ctypes.c_double*2)(0.0,1.0)
p_y = (ctypes.c_double*2)(0.0,1.0)
p_z = (ctypes.c_double*2)(0.0,1.0)
p = ((ctypes.c_double*2)*dim)(p_x,p_y,p_z)
cmplx = cellComplex_lib.new_cellComplex(p,dim)
^This doesn't work and I don't know why.
Problem 2. (Included here because it's glaring in Problem 1) I am returning an essentially anonymous pointer from my C code! This just feels, well, dirty, and there must be a better way to return a custom data type and deal with it back in Python. For the record, I am extremely grateful for this stackoverflow answer where I learned such sorcery - but I'm not going to be able to sleep at night as long as it's in my code...
Instead of double **, use double [][2]. You're passing a contiguous C array that you want to access as a pointer to a row of 2 items. The first index is the row index.
Declaring the array as a double ** is a pointer to a double pointer, so p[i] is a pointer, and p[i][0] dereferences it again. But p[i] is a NULL pointer by chance according to your data.
Refer to the comp.lang.c FAQ, question
6.18: My compiler complained when I passed a two-dimensional array to a function expecting a
pointer to a pointer.
For the return type, you can subclass c_void_p, or use the hooks from_param and _as_parameter_ per the last paragraph of section 15.17.1.7 in the ctypes docs.

Two dimensional array / initialize data in c++ (Arduino)

I think I lost my whole C++ knowledge...
What I want is to initialize a 2D unsigned char array in a proper (readable) way:
My approaches:
#define RADIO_ONOFF 0
#define RADIO_P1 1
#define RADIO_P2 2
...
#define NR_OF_CODES = 5
#define CODE_LENGTH = 10
#1:
unsigned char** codes = new unsigned char*[NR_OF_CODES];
codes[RADIO_ONOFF] = new unsigned char[CODE_LENGTH]{ 9,180,88,11,33,4,0,255,64,191 }; // does not work
...
#2:
unsigned char ICODES[NR_OF_CODES][CODE_LENGTH];
ICODES[RADIO_ONOFF] = { 9,180,88,11,33,4,0,255,64,191 }; // same as above
...
#3:
class Test {
private:
unsigned char data[CODE_LENGTH];
public:
Test(unsigned char a1, unsigned char a2, unsigned char a3, unsigned char a4, unsigned char a5, unsigned char a6, unsigned char a7, unsigned char a8, unsigned char a9, unsigned char a10);
unsigned char* getData(void);
};
Test::Test(unsigned char a1, unsigned char a2, unsigned char a3, unsigned char a4, unsigned char a5, unsigned char a6, unsigned char a7, unsigned char a8, unsigned char a9, unsigned char a10) {
this->data[0] = a1;
this->data[1] = a2;
this->data[2] = a3;
this->data[3] = a4;
this->data[4] = a5;
this->data[5] = a6;
this->data[6] = a7;
this->data[7] = a8;
this->data[8] = a9;
this->data[9] = a10;
}
unsigned char* Test::getData(void) {
return data;
}
void setup() {
test[RADIO_ONOFF] = new Test( 9,180,88,11,33,4,0,255,64,191 );
test[RADIO_P1] = new Test( 9,180,88,11,33,4,0,255,64,192 );
...
}
#4
const unsigned char RADIO_ONOFF[] = { 9,180,88,11,33,4,0,255,64,191 };
const unsigned char RADIO_P1[] = { 9,180,88,11,33,4,0,255,64,192 };
...
Error message I get for #1 and #2: (code should compile for Arduino and it needs a setup-function)
In function 'void setup()':
revTest:58: error: expected primary-expression before '{' token
revTest:58: error: expected `;' before '{' token
OK - my questions:
To me - #3 and #4 are nice and readable. Effort for #3 is the highest - but I think it´s the
fastest way if I want do uses the array in a switch statement. - True?
I thought array initialization in #1 and #2 should work this way????
Very Arduino specific:
I am not sure what has to be defined inside of setup() and what should go outside of setup(). static initialization and global outside, dynamic inside or what?
I have red about PROGMEM for Arduino - I think it´s not worth the effort in this case. I am right? (I think I`ll have about 50 different codes...)
thx!
Before answering your questions, let's look at what's going wrong with solutions 1 and 2.
The problem with solutions 1 and 2 is that you're using an initialiser ( i.e. the `{} syntax ), where your compiler is expecting an assignment expression.
Initialisation syntax can only be used at the point where the variable is declared. Roughly speaking, initialisation should be understood as giving a value to a variable as soon as it is constructed. Assignment should be understood as giving a value to a variable that has already been constructed somewhere else.
So when you do:
unsigned char** codes = new unsigned char*[NR_OF_CODES];
You are doing initialisation. You are initialising the variable codes to a freshly allocated array of pointers to unsigned char.
On the next line, you are then telling the compiler you are doing an assignment. You're using the = sign and assigning to codes, which was declared on the previous line - compiler sees this as assignment.
codes[RADIO_ONOFF] = new unsigned char[CODE_LENGTH] ...
But then, immediately afterwards, you attempt to use initialisation syntax.
Your compiler is complaining because it's read this:
codes[RADIO_ONOFF] = new unsigned char[CODE_LENGTH] ...
as a complete expression. It read that as you're allocating an array of CODE_LENGTH bytes and assigning it to the RADIO_ONOFF th member of codes.
And it expected you to stop there, with a semi colon but you continued and added the initalisation syntax {}. It doesn't understand, because you are mixing assignment and initialisation together - which are two separate things. That's why you're getting the "I expect a semi colon" type error from the compiler.
To answer your questions, both solution 3 and 4 are taking the long way round. There are quicker ways of initialising a 2D array in C++. I also agree with previous answer about using uint8_t.
Would something like this be more suitable?
uint8_t codes[CODE_LENGTH][NR_OF_CODES] =
{{0, 1, 2, 3, 4, 5, 6, 7},
{0, 1, 2, 3, 4, 5, 6, 7},
{0, 1, 2, 3, 4, 5, 6, 7},
{0, 1, 2, 3, 4, 5, 6, 7} };
A good way to read array syntax is to take the final (rightmost) value in the square brackets [] as the size of some array, and then work backwards.
So uint8_t codes[CODE_LENGTH][NR_OF_CODES] will decode out to an array of size NR_OF_CODES of something. And to get that something go left, and we see uint8_t codes[CODE_LENGTH] - so it's an array of length NR_OF_CODES of arrays of uint8_t, each of length CODE_LENGTH.
I hope that helps.
NB. In answer to your comment about needing to index the array with named indices - there's nothing stopping you from referring to the individual members of codes via an index.
What you can do is initialise the whole thing via {0} - shorthand for initialising all members to 0.
And you can assign members of the RADIO_ONOFF array (or any array for that matter) individually e.g.
codes[RADIO_ONOFF][3] = 255;
Try this example - and note the output:
#include <iostream>
const int NR_OF_CODES = 4;
const int RADIO_ONOFF = 0;
const int CODE_LENGTH = 11;
const unsigned char RADIO_ONOFF_ARR[] = { 180,99,33,11,22,33,55, 22,22,33, 10};
int main()
{
unsigned char codes[CODE_LENGTH][NR_OF_CODES] = {
{0},
};
std::cout << "Before:\n";
for(int x = 0; x < CODE_LENGTH; x++)
{
std::cout << static_cast<int>(codes[RADIO_ONOFF][x]) << ", ";
}
codes[RADIO_ONOFF][3] = 3;
std::cout << "\nAfter:\n";
for(int x = 0; x < CODE_LENGTH; x++)
{
std::cout << static_cast<int>(codes[RADIO_ONOFF][x]) << ", ";
}
// or try memcpy
memcpy(codes[RADIO_ONOFF], RADIO_ONOFF_ARR, sizeof RADIO_ONOFF_ARR);
std::cout << "\nAfter Memcpy:\n";
for(int x = 0; x < CODE_LENGTH; x++)
{
std::cout << static_cast<int>(codes[RADIO_ONOFF][x]) << ", ";
}
char c;
std::cin >> c;
return 0;
}
First off all, since this is tagged C++, I'm going to say that there is no need to do #define. You now have access to static const variables that do the same, but are type safe.
Here's what the Google C++ style guide has to say about braced lists:
http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Braced_Initializer_Lists
I generally follow this guide when I'm not working on a project with an already setup style. Also, I should mention that style is really subjective, so you may end up getting a wide range of answers.
Also, don't use char, where you just want to store byte data. That's what uint8_t is for.
Also, see this SO thread for all your options of how to initialize your arrays: How to initialize all members of an array to the same value? In most of your cases since they are just holding non-changing constants, you can get away with making them static const.
Like this:
static const size_t kMyCodeArraySize = 14; // an example
static const uint8_t[kMyCodeArraySize] = {1, 2, 3, 4}; // example intialization

What is the easiest way to set the value of an entire array?

My current project requires me to fill an array based upon some other values. I know there's the shortcut:
int arr[4][4] = { {0,0,0,0} , {0,0,0,0} , {0,0,0,0} , {0,0,0,0} };
But in this case, I need to fill the array after its declaration. I currently have my code formatted like this:
int arr[4][4];
if(someothervariable == 1){
arr = { {1,1,1,1},
{1,2,3,4},
{2,,3,4,5},
{3,4,5,6} };
}
But it won't compile. Is there a way to make use of the mentioned shortcut in my case? If not, whats the best fix available? I'd appreciate a way to set it without explicitly assigning each element? ie: arr[0][0] = ...
How about using std::copy() ?
int arr[4][4];
if(someothervariable == 1){
const static int a2[4][4] = { {1,1,1,1},
{1,2,3,4},
{2,3,4,5},
{3,4,5,6} };
std::copy(&a2[0][0], &a2[0][0]+16, &arr[0][0]);
}
No, array initialization syntax is for array initialization. Although, you can use memset if all the values are the same byte.
The boost.assign library adds some interesting syntax for modifying/filling collections, but AFAIK it doesn't support C style arrays (only C++ and Boost containers).
In the current version of C++ language the only way to do it is to copy it from some original
int arr[4][4];
if (someothervariable == 1)
{
const int SOURCE[4][4] = // make it `static` if you prefer
{
{1, 1, 1, 1},
{1, 2, 3, 4},
{2, 3, 4, 5},
{3, 4, 5, 6}
};
assert(sizeof arr == sizeof SOURCE); // static assert is more appropriate
memcpy(&arr, &SOURCE, sizeof arr);
}
The source "constant" can be declared as static in order to avoid re-initialization, if the compiler is not smart enough to optimize it by itself.
In the future version of the language a feature similar to C's compound literals is planned, which will provide support for immediate initialization (basically what you tried to do in your original post).
If you wish to fill the array with a single value:
#include<algorithm>
#include<vector>
// ...
std::vector<int> arr;
std::fill(arr.begin(), arr.end(), VALUE); // VALUE is an integer
If you wish to calculate the value for each element:
struct get_value {
int operator()() const { /* calculate and return value ... */ }
};
std::generate(arr.begin(), arr.end(), get_value());
If you are setting everything to the same value (such as zero), you may be able to get away with ...
memset (arr, 0, sizeof (arr));
Note that this is fraught with perils. You have to know your type sizes and all that jazz.
However, it appears that that will not suffice for you. If you want to fill the array with different values, I can only only think of two ways of doing this.
Method #1. (Can be a pain the butt)
arr[0][0] = 1;
...
arr[0][3] = 1;
arr[1][0] = 1;
...
arr[1][3] = 4;
arr[2][0] = 2;
...
arr[2][3] = 5;
arr[3][0] = 3;
...
arr[3][3] = 6;
Method #2.
Predefine a set of arrays and switch between them using a pointer;
int arr1[4][4] = {
{0,0,0,0},
{0,0,0,0},
{0,0,0,0},
{0,0,0,0} };
int arr2[4][4] = {
{1,1,1,1},
{1,2,3,4},
{2,,3,4,5},
{3,4,5,6} };
int *arr[4];
Now you only have the four (4) values of *arr[] to set instead of setting everything. Of course, this really only works if your arrays will be filled with predetermined constants.
Hope this helps.
I'm not sure if I like this solution or not, but C/C++ will give you assignment convenience if you wrap the array inside a struct with the minor cost of then having to use the struct name to get at the array:
typedef struct {
int data[4][4];
} info_t;
info_t arr;
if (someothervariable == 1){
static const info_t newdata = {{ // since this is static const, there generally
// won't be a copy - that data will be 'baked'
// into the binary image (or at worst a
// single copy will occur)
{1,1,1,1},
{1,2,3,4},
{2,3,4,5},
{3,4,5,6}
}};
arr = newdata; // easy to assign new data to the array
}
int somethingelse = arr.data[1][2]; // a tiny bit less convenient to get
// to the array data
int arr[4][4];
if (someothervariable == 1) {
int tmp[4][4] = { {1, 1, 1, 1}, {1, 2, 3, 4}, {2, 3, 4, 5}, {3, 4, 5, 6} };
arr = tmp;
}