6

I have a problem when I try to pass the pointer of an array (which contains parameters needed by some functions in my program) to a structure, which then should be passed to those functions. GSL for example wants me to pass parameters in this way.

A little example program looks like this:

#include <iostream>

using namespace std;

struct myparams
{
    double  * a;
    double ** b;
};

int main()
{
    double c[10]   = {0,1,2,3,4,5,6,7,8,9};
    double d[4][3] = {{1,2,3},{4,5,6},{7,8,9},{10,11,12}};

    double** e = new double*[4];
    for (int i = 0; i < 4; i++) {
       e[i] = new double[3];
    }

    myparams params;

    // THIS WORKS:
    params.a = c;
    for (int i = 0; i < 10; i++) {
        cout << params.a[i] << endl;
    }

    // THIS DOESN'T WORK
    params.b = d;

    // THIS WORKS:
    params.b = e;

    delete[] e;
}

What is the problem with

 params.b = d

The Compiler complains with "cannot convert 'double[4][3]' to 'double**' in assignment" or something like that (translated from german).

3

2 Answers 2

11

double d[4][3]; is an array of arrays. double b**; is a pointer to pointer. These types are not the same (the common "arrays are just pointers" you might have read on the internet is wrong).

Elements of d are of type double[3]. Arrays, when passed around, decay to pointers to their first element (see section 4.2. of C++ standard). d will decay to double(*)[3] (a pointer to array of 3 doubles).

Long story short, double(*)[3] is not convertible to double** and this is what compiler is telling you.

If you need to keep d as it is, you need to declare b as double (*b)[3];

For more in-depth explanation, refer to this SO question.

Sign up to request clarification or add additional context in comments.

5 Comments

Thank you! This was almost the solution. It's not double (*b)[4], but double (*b)[3].
I like how you accepted the incorrect answer over the correct one. That makes sense.
@LightnessRacesinOrbit If you point out what's incorrect, I'll fix it. Thank you.
@jrok: GriffinPeterson (the OP!) already did. Read his comment.
@LightnessRacesinOrbit Aye, typo.
8

It's because a pointer to a pointer (or an array of pointers as it can be used as) is not the same as an array of arrays. The layout in memory is incompatible.

For example, lets say we have these two declarations:

char aa[2][2] = { { 'a', 'b' }, { 'c', 'd' } };
char **pp;

pp = new char*[2];
pp[0] = new char[2];
pp[1] = new char[2];

The array aa looks like this in memory:

+----------+----------+----------+----------+
| aa[0][0] | aa[0][1] | aa[1][0] | aa[1][1] |
+----------+----------+----------+----------+

The "array" pp meanwhile looks like this:

+------+------+
| a[0] | a[1] |
+------+------+
   |      |
   |      v
   |      +---------+---------+
   |      | a[1][0] | a[1][1] |
   |      +---------+---------+
   V
   +---------+---------+
   | a[0][0] | a[0][1] |
   +---------+---------+

The "array" pp contains pointers to another "array"

11 Comments

Thank you for the quick response! But which member do I need in my structure myparams to store the pointer to the array d?
Okay I think that's better than my diagram. Dammit.
@LightnessRacesinOrbit Well, I think yours look more "professional" than my crude ASCII art :)
@JoachimPileborg: I did it in pbrush!
@GriffinPeterson: It's unwieldy, though. You're much better off with a 1D array representation.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.