2

The following code is invalid:

int main()
{
    int n =5;
    float ** p = new float[n][5]; //error: cannot initialize a variable of type 
                                  //'float **' with an rvalue of type 'float (*)[5]'
}

demo

I expected that after applying new operator to float[n][5], float** will be returned. So what exactly type will be returned by new float[n][5]?

UPD: The following code is valid:

int main()
{
    float* p[5];
    float ** t = p; //OK
}

demo

11
  • 5
    The compiler gave you the type: float(*)[5]. Commented Jul 26, 2014 at 18:52
  • Because float** != float(*)[5]. Commented Jul 26, 2014 at 18:55
  • @chris Could you check my updated question? Commented Jul 26, 2014 at 18:57
  • In order for a float** to work as a multidimenstional array (or pseudo-array), you need an array of float*. new float[n][5] does not allocate an array of float*. Commented Jul 26, 2014 at 18:58
  • 1
    Your latter example works because p is an array of float*, which is not what is created by new float[n][5]. Commented Jul 26, 2014 at 18:59

5 Answers 5

2

The error message showed what is the returned type

float (*)[5]

That is it is pointer to an array with 5 elements of type float.

As for float ** then it is pointer to a pointer to an object of type float, To see the difference execute the following code

float ( *p1 )[5];
float **p2;

std::cout << sizeof( *p1 ) << std::endl;
std::cout << sizeof( *p2 ) << std::endl;

It is the values that are used in the pointer arithmetic, For example if p1 was initialized then ++p1 will have an address that is sizeof( *p1 ) greater than the initial address

That it would be more clear consider the following code

typedef float T1[5];
typedef float *T2;

std::cout << sizeof( T1 ) << std::endl;
std::cout << sizeof( T2 ) << std::endl;

T1 *p1 = new T1[5];
T2 *p2 = new T2[5];
Sign up to request clarification or add additional context in comments.

2 Comments

I didn't know it. Has it explained in the Standard?
@Dmitry Fucintv You should see definitions of declarators.
2

float (*)[5] is pointer to array 5 of float which is what new float[n][5] is returning.

float **p declares a pointer to pointer to float, which is not same as float (*)[5]

float* p[5]; declare an array 5 of pointer to float

You can do following instead :

  • float (*p)[5] = new float[n][5];
  • float **p = new float* [5];

Comments

0

If the lower dimension is indeed constant (5), then you can use this:

typedef float float_arr[5];

int main()
{
    int n = 5;
    float_arr* p = new float_arr[n];
    ...
}

Comments

0

The way an array is dereferenced is like so:

float* data = float [8];
data[5] = *(data + 5);

float* data = float [10][3];
data[7][1] = *(data + ((10 * 7) + 1));

float* data = float [2][4][6];
data[2][3][5] = *(data + ((((2 * (2 * 4)) + (3 * 4)) + 5);

etc

Multi-dimensional arrays are implemented as just arrays and the compiler specifies the additional math needed for the dimensions after the first. This is different from having an array of pointers to floats, which is what float** points to.


For additional clarification, in the case of float** p = new float [n][5];, the memory allocated is SIZEOF(float) * n * 5 bytes and p is set to a pointer to that memory. The compiler does not allow you to assign to a float** for good reason, not because it is forcing you to keep with standards or conventions or something. If you were to dereference it manually as you would a valid one-dimensional float** to a one-dimensional array of floats, in a way such as (for example, second element in third row) *(*(p + (n * 2)) + 1), then the float would be read as a pointer type, probably UINT32 or UINT64 on most modern systems, and so in either case the float would be dereferenced, almost certainly on an invalid location, causing a memory access violation, or otherwise to some valid location that has other data and would still certainly not be what you intended to get. And on top of that, in the case of 64-bit systems, you could get a memory access violation already on the first stage if the array were allocated as float** p = new float [1][1];, because the 64-bit pointer expected would be larger than the float allocated, as they are typically 32 bits in size.

Comments

0

Try this

int n =5;

typedef float * FloatPointer;

FloatPointer p[] = { new float[5], new float[5], new float[5], new float[5], new float[5], };

As n is not a const value compiler can't allocate space a compile time.

Comments

Your Answer

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