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

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • 5
    The compiler gave you the type: `float(*)[5]`. – chris Jul 26 '14 at 18:52
  • Because `float** != float(*)[5]`. – 101010 Jul 26 '14 at 18:55
  • @chris Could you check my updated question? –  Jul 26 '14 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*`. – Benjamin Lindley Jul 26 '14 at 18:58
  • @40two So why my latter example works? –  Jul 26 '14 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]`. – Benjamin Lindley Jul 26 '14 at 18:59
  • Hope this clarifies things for you: [LIVE DEMO](http://coliru.stacked-crooked.com/a/d2e8e2ebc52d1a48) – 101010 Jul 26 '14 at 19:03
  • @DmitryFucintv, Read up on [arrays](http://stackoverflow.com/questions/4810664/how-do-i-use-arrays-in-c). That covers all of this. – chris Jul 26 '14 at 19:08
  • A little tip. When you call `delete` it needs to know the size of the inner array so it knows how much to delete. – Cole Tobin Jul 26 '14 at 19:21
  • In C++ you can use pointers as a pointer or as an array, You are trying to do both. There is a difference between a pointer and array, an array requires you to initialize it`s length and if you want to use a pointer as an array too, you have to initialize its length or size."*" represent a single pointer not multiple pointers unless you initialize its size to be 5 or 10, then you will have 10 pointers. You have double pointers and what than means is that, you have one pointer "P" that points to 5 pointers. To initialize "P" you do this: float **p = new float*[5]; – Juniar Jul 26 '14 at 21:03
  • To initialize double pointers you need to do this: float **p = new float *[5]; for(int i = 0; i < 5; i++){p[i] = new float[5];} The first line initializes the second pointer and the for loop initializes the first pointer. – Juniar Jul 26 '14 at 21:37

5 Answers5

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];
P0W
  • 46,614
  • 9
  • 72
  • 119
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];
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
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];
    ...
}
barak manos
  • 29,648
  • 10
  • 62
  • 114
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.

rsethc
  • 2,485
  • 2
  • 17
  • 27
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.

Tim Child
  • 2,994
  • 1
  • 26
  • 25