14

C arrays are somewhat difficult to understand syntactically in C++ and can take some getting used to. Although a 1D array decays to a pointer:

void fn1(int x[2]) {}
void fn2(int*x) {}

fn1() and fn2() have the same function signature.

An array actually does have a type that includes how many elements are in the array. As in:

void fn(int (&)[2]) {}

fn() will only accept a 2 element int array.

Thing is, I can only see that the array of a fixed number of elements can only be generated by stack, file scope or struct/class allocation with that signature:

int twoElementArray[2];

If I were to dynamically allocate it on the heap, I can't seem to get the same signature. I thought that I might be able to cast it, but without success:

int (&array)[2] = reinterpret_cast<int(&)[2]>(new int[2]); // FAIL!

Any ideas as to how this might be accomplished if at all?

 


EDIT: Although I selected an answer, it actually doesn't actually cast anything, but uses a definitely better method then casting (better not to cast if not required IMO). However, it technically doesn't answer the question since the question asked if there's "a way of casting a pointer to an array type?" The answer is yes.

int (&array)[2] = *reinterpret_cast<int(*)[2]>(new int[2]); // SUCCESS!

Note that I don't necessarily recommend doing this, but it does answer the question. If I needed to convert a pointer to an array type though, that would be how to do it. Read the picked answer for a better solution when using operator new[].

9
  • you could throw in template and make int FIXED_SIZE = 2. Commented Jun 23, 2013 at 8:04
  • @Infested: Sorry, I don't understand what you mean. Could you explain further and perhaps add an example? Commented Jun 23, 2013 at 8:06
  • if fn1 only accepts a fixed size of the array, then simply make it a template function and it should get two things , int[] , int FIXED_SIZE = 2, then you can have int x[FIXED_SIZE] Commented Jun 23, 2013 at 8:10
  • @Infested: fn1() was part of my explanation as to how arrays work in C++ for the uninitiated. Yes, I could do: void fn3(int* array, size_t FIXED_SIZE) {} or alternatively void fn3(int[] array, size_t FIXED_SIZE) {} which is a common workaround. However, I was trying to utilise the type system to stop the decoupling of the array from it's size. Commented Jun 23, 2013 at 8:24
  • have you tried doing int [] x ? Commented Jun 23, 2013 at 8:38

3 Answers 3

10

If I understand your problem correctly, you'd want to do something like this:

// allocate an array of one int[2] dynamically
// and store a pointer to it
int(*p)[2] = new int[1][2];

// now initialize a reference to it
int(&array)[2] = *p;

// delete the array once you no longer need it
delete[] p;
Sign up to request clarification or add additional context in comments.

Comments

1

I think this is what you are looking for. For the heap, a two-dimensional array int[M][N] decays to int(*)[N]. To pass it by reference, dereference it (see m below):

#include <iostream>
using namespace std;

void func(int (&x)[2])
{
    cout << x[0] << ' ' << x[1] << endl;
}

int main()
{
    // on the heap
    auto m = new int[1][2];
    m[0][0] = 1; m[0][1] = 2;
    auto n = new int[1][3];
    n[0][0] = 4; n[0][1] = 5; n[0][2] = 6;

    // on the stack
    int o[2] = {7,8};
    int p[3] = {9,10};

    func(*m);
    //func(*n); // doesn't compile, wrong size
    func(o);
    //func(p); // doesn't compile, wrong size
}

Output:

1 2
7 8

1 Comment

+1 for using the proper terminology decays. I corrected my question to use the same terminology.
-1

Based on Mark answer, this could be better:

template <typename T>
void func(const T &x)
{
    cout << x[0] << ' ' << x[1] << endl;
}

the only bad think is that this code is valid:

cout << x[3] << endl;

1 Comment

Sorry, this answer is just wrong. You have just made a template function that takes a const ref of any type. It doesn't take an array at all. Go and try to compile it. You probably meant something along the lines of template <typename T> void func(const T (&x)[2]) {...} or template <typename T, size_t N> typename std::enable_if<(N>=2)>::type func(const T (&x)[N]) {...}. However, that's also assuming that I want to take in any type and not just an int, which isn't what the question asked.

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.