C++ casting static two-dimensional double array to double** - c++

I have such matrix in my program:
double m[3][4] =
{
{2, 4, 5, 7},
{4, 5, 1, 12},
{9, 12, 13, -4}
};
And I'd like to cast it to double** type.
I've already tried simple double** a = (double**)m;, but it doesn't work (when I try to read any value, I get "Access violation reading location 0x00000000.", which means I'm trying to read from NULL adress.
I found almost working solution:
double *b = &m[0][0];
double **c = &b;
It works when I read field c[0][any]
But same NULL adress reading problem occurs, when I try to read value from field c[1][0].
What is the proper way to cast my double m[3][4] array to type double**?
edit:
You say that's impossible. So I'll change a problem a little bit. How can I pass two-dimensional double array as a parameter to a function? My function has prototype:
void calculate(double **matrix, int n); //where matrix size is always n by n+1
And it's working fine with dynamically-allocated arrays. I doubt that only way to make it work is allocating new dynamical array and copy original static array one element by another...

You can't.
The notation double** refers to an array of pointers. You don't have an array of pointers, you have an array of arrays of doubles.

You can't just cast the array. You are going to have to create something like this:
double m[3][4] =
{
{2, 4, 5, 7},
{4, 5, 1, 12},
{9, 12, 13, -4}
};
double *marray[3] = {m[0],m[1],m[2]};
calculate(marray,3);
Or you can use a loop:
const size_t n = 3;
double *marray[n];
for (size_t i=0; i!=n; ++i) {
marray[i] = m[i];
}
calculate(marray,n);

When you write
double m[3][4]
{
{2, 4, 5, 7},
{4, 5, 1, 12},
{9, 12, 13, -4}
};
The compiler actually creates an array of doubles as if you had written
double _m[] = {2, 4, 5, 7, 4, 5, 1, 12, 9, 12, 13, -4};
However, thanks to C/C++ type system, the compiler remembers that m's type
is double [3][4]. In particular it remembers the sizes 3 and 4.
When you write
m[i][j]
the compiler replaces it by
_m[i * 4 + j];
(The 4 comes from the second size in double [3][4].) For instance,
m[1][2] == 1 and _m[1 * 4 + 2] == _m[6] == 1 as well.
As others said, a double** is a different type which doesn't carry the
sizes with it. To consider double** a as a 3 x 4 matrix, a[0], a[1] and
a[2] must be pointers to double (that is, double*) pointing to the
first element of the corresponding row. You can achieve this with
double* rows[] = { &m[0][0], &m[1][0], &m[2][0] };
double** a = &rows[0];
A simple cast doesn't create the variable rows above. Let me present other
alternative (but equivalent) ways to define rows
double* rows[] = { &m[0][0], &m[0][0] + 4, &m[0][0] + 2 * 4};
double* rows[] = { &_m[0], &_m[4], &_m[2 * 4]};
As you can see, only the second size (i.e. 4) is necessary. In general, for
multi-dimensional arrays, all sizes but the first are required. For this
reason a 1-dimensional array
double x[4] = { 1, 2, 3, 4 };
can be implicitly converted to a double*
double* y = x;
Using this fact we can also write
double* rows[] = { _m, _m + 4, _m + 2 * 4};
Indeed, _m is converted to a double* pointing to m[0]. Then, in _m + 4,
_m is is converted to a double* pointing to m[0] and to this pointer
it's added 4. Hence, _m + 4 is a pointer the fourth double following
_m[0], which is _m[4] and so on.
So far I have explained why you cannot cast a double [3][4] (or any other sizes) to a double**. Now, I'shall show, in your particular case, how calculate can be defined.
template <int N>
void calculate(double (&m)[N][N+1]) {
// use m as a double[N][N+1]
}
You call
calculate(m);
and the compiler will deduce the size N for you. In general (i.e, when the second dimension is not the N + 1) you can write
template <int N, int M>
void calculate(double (&m)[N][M]) {
// use m as a double[N][M]
}

If you're always using arrays (no pointers) for initialization, and you are able to avoid the pointer stuff in your calculate function, you might consider the following option, which uses size deduction by templates.
template<int m, int n>
void doubleFunc(double (&mat)[m][n])
{
for (auto i = 0; i < m; i++)
{
for (auto j = 0; j < n; j++)
{
std::cout << mat[i][j] << std::endl;
}
}
}
It worked during my quick test.
double m[3][4] =
{
{2, 4, 5, 7},
{4, 5, 1, 12},
{9, 12, 13, -4}
};
doubleFunc(m);

You can pass a 2d array as a function parameter:
void calculate(double matrix[][y], int n);

Until variable-length arrays are in the C++ standard, your choices include:
If your compiler supports variable-length arrays as an extension, you can likely pass them with a function declaration such as void foo(std::size_t n, double a[][n+1]). Note that the compiler likely requires n to be passed before a parameter declaration that uses n or requires some special syntax.
You can pass a double * and do index arithmetic manually in the function: void foo(std::size_t n, double *a) { … a[row*(n+1) + column] … }
You can create a class the implements variable-length arrays by doing the index arithmetic in its accessor functions.
You can allocate space for n pointers to double, fill those pointers with pointers to each row of the array, and pass the address of the space.

Related

How to place variadic template arguments into an array?

I want to have a variable number of arguments to a function and inside that function I want to place them into an array. I tried to use a fold expression for this because I didn't understand what they did. I thought they just simply expanded the arguments with a comma in between:
template <typename ... var_args_t>
void putArgumentsToArray(var_args_t&& ... values)
{
constexpr int num_args = sizeof ... (var_args_t);
int values_array[num_args] = {
(values, ...)
};
for (int i = 0; i < num_args; ++i)
std::cout << values_array[i] << "\n";
/* PRINTS [6, 0, 0, 0, 0, 0]*/
}
int main()
{
putArgumentsToArray(1, 2, 3, 4, 5, 6);
}
The end result is that the array is only initialised with one value(6), because all six arguments are evaluated as expressions, however the comma operator works so that only the last argument is returned. So the array has only one initialiser.
I know I can use a std::vector or a loop, but it would be really nice and clean if I could do this directly into the array initialiser.
You have confused the syntax a bit. You wished parentheses on other places
int values_array[num_args] = {
(values)...
};
or the same but without parentheses
int values_array[num_args] = {
values...
};
values... expands to
1, 2, 3, 4, 5, 6
Whereas (values, ...) expands to the comma operator in the parentheses
(1, 2, 3, 4, 5, 6)
that returns the single 6, the value of the last operand of the comma operator.

Question about the array's address in C++

I have a question about the array's address.
Is *(a + *a) the same as a[3]? If it is, please give me some explanation.
int main() {
int a[] = { 1, 2, 3, 4, 5, 6};
*(a + *a);
}
Is (a + *a) same as a[3]??
No, it is not.
No. *a is equal to 1, so cout << a + 1 will output address of a incremented by 4, which is the size of an int type. This is because a is an array of int, so every increment will add it's address by sizeof(int), which is 4.
a is the address of the first element of the array. *a is the value located at the first element of the array. So a+*a is the sum of those two values, which is not the same as a[3].
If the first element of the array happened to be 3, then *(a+*a) would be the same as a[3]. But that is not the situation you have. i.e. *a=3, (a+3) is the location of the fourth element of a, *(a+3) is the element at the fourth location of the array, which is also accessible using a[3].
To generalize for a given X* x or X x[] that can decay into a pointer:
*(x + y) is the same as x[y].
*x is the same as x[0]
In effect *(a + *a) is just a really confusing way of writing a[a[0]], so the way it evaluates depends entirely on what a[0] is.
In this case it's 1, so you get a[a[0]] or a[1] as the result.

Copy section of an array into a std::vector in C++

Hello im wondering if its possible to copy a section of an array whilst initializing a vector.
For example I have tried
UINT16 myarray[] = { 0,1,2,3,4,5,6, ..., n };
std::vector<UINT16> myvect(myarray[3], myarray[3] + 16);
This kind of works however I seem to get more data than i intended. Is this the correct usage?
The way is to pass iterators, not values
std::vector<UINT16> myvect(myarray + 3, myarray + 3 + 16);
UINT16 myarray[] = { 0,1,2,3,4,5,6, ..., n };
std::vector<UINT16> myvect(myarray[3], myarray[3] + 16);
This uses myarray[3] which is 3 and myarray[3] + 16 which is 19 as arguments to the myvect constructor. Which in turn sets up myvect to contain 3 elements, all with the value 19.
If you want a copy of the 16 elements starting at index 3, you can do it like this:
std::vector<UINT16> myvect(&myarray[3], &myarray[3 + 16]);
Here is a different (more verbose) way:
uint16_t myarray[] = { 0, 1, 2, 3, 4, 5, 6, ..., n };
constexpr auto arr_size = sizeof(myarray) / sizeof(myarray[0]);
constexpr auto copy_start = std::min< size_t >(3, arr_size);
constexpr auto copy_count = 19;
constexpr auto copy_end = std::min< size_t >(copy_start + copy_count, arr_size);
vector< uint16_t > myvect(std::next(myarray, copy_start), std::next(myarray, copy_end));
Instead of UINT16 you can use uint16_t type from C++11 onwards: Fixed width integers (if your compiler supports it)
If your values are available at compile time, then you can use compile time constants(constexpr) to calculate the helper variables. Otherwise const should be used.
Standard algorithms can be used also on arrays so providing an offset to std::next can be used to get the n-th element of an array.

How do I make a C++ function implicitly convert a list of ints into a vector parameter?

I am working on a library whose functions commonly take a vector type (__v4si, or a vector of 4 signed ints) as a parameter. (Note that so far this has nothing to do with the C++ STL vectortemplate class; this is a more primitive construct used to let the compiler generate vectorized SIMD code.)
In my C code I customarily call a wrapper macro that takes a list of int arguments and initializes a __v4si like so:
#define MakeIndex(dims...) ((__v4si){ dims })
This of course works fine in C++ too, but I would like to take advantage of C++'s more expressive type system to clean up calls to my libraries APIs. For example, where I now write something like:
long idx = IndexDotProduct(MakeIndex(1, 2, 3), MakeIndex(4, 5, 6, 7));
which macro-expands to:
long idx = IndexDotProduct(((__v4si){1, 2, 3}), ((__v4si){4, 5, 6, 7}));
I would like instead to be able to write something along the lines of:
long idx = IndexDotProduct({1, 2, 3}, {4, 5, 6, 7});
So, essentially (I think) I want to define a class that is just syntactic sugar around the primitive __v4si type, but that has an implicit cast operator for the list initializer.
How do I do that in C++ 11?
Solution
Here is a formulation that works for both C and C++ code (now using more verbose names as copied and pasted from my library header files):
typedef struct vMAT_Index {
__v4si v;
#ifdef __cplusplus
vMAT_Index(__v4si v) : v(v) { }
vMAT_Index(int v0 = 0, int v1 = 0, int v2 = 0, int v3 = 0) : v((__v4si){ v0, v1, v2, v3 }) { }
#endif
} vMAT_Index;
#define vMAT_MakeIndex(dims...) ((vMAT_Index){ .v = { dims } })
static inline long
vMAT_Index_dot(vMAT_Index a,
vMAT_Index b)
{
__v4si c = a.v * b.v;
return (long)c[0] + c[1] + c[2] + c[3];
}
In C code you still use the helper macro like this:
long idx = vMAT_Index_dot(vMAT_MakeIndex(1, 2, 3), vMAT_MakeIndex(4, 5, 6, 7));
But now in C++ you can just write:
long idx = vMAT_Index_dot({ 1, 2, 3 }, { 4, 5, 6, 7 });
Thanks to nosid for providing the essential answer!
Use implicit constructors to automatically create a vector object from a brace-initializer list:
struct vector
{
vector(__v4si v);
vector(int i0, int i1, int i2, int i3);
};
long IndexDotProduct(vector lhs, vector rhs);
long idx = IndexDotProduct(((__v4si){ 1, 2, 3 }), { 4, 5, 6, 7 });

Sorting a 2d array

I am trying to sort two sets of data, that are either in a 2d array or parallel arrays, either way it makes no difference but I cant seem to figure it out. Here are the two arrays:
/////way one///
int id[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int numDetected[10] = {40, 21, 2, 19, 45, 32,43, 90, 100, 8};
or
int 2dArray[2][10];
it makes no difference, but I cant seem to figure this out.
I want to order the arrays into a new array, (whether it is a 2d array or parrellel arrays) by the numDetected amount. So the largest numDetected is at element zero and the smallest at the end. But while doing that, I want to keep the id associated with that in the same element as the numDetected. So if numDetected[2] is the largest, I want numDetected[2] and id[2] to be the first elements in the new arrays.
Can anyone help me out?
struct values
{
int id;
int detected;
} data[10] = ...;
// intentionally reversed to cause sort in descending order
bool operator<(const values& left, const values& right) { return left.detected > right.deteted; }
values *begin = data, *end = (&data)[1];
std::sort(begin, end);