2

I have an object which has a 2d char array as a property.

I'd like to create an accessor method which is able to return a pointer to this 2d array.

I have declaired the 2d array like this:

#define PRESET_LEN 15
#define NO_PRESETS 8

char camPresets[NO_PRESETS][PRESET_LEN];

Being new to C++ I'm having a bit of bother trying to fiigure out the method declairation.

So far I have this in the header :

char** getPresetsForCamera(int cam);

and this in the cpp

char** DataManager::getPresetsForCamera(int cam)
{
    if(currentCam != cam)
        load(cam);

    return camPresets;
}

But it does not compile. I obviousely havn't understood how to use pointers properly, at least for 2d arrays, I thought I could just write 'return &camPresets;' to return the address of the array but I'm wrong. Please could someone show me where I'm going wrong. Thanks, Rick.

Rick Bush
  • 81
  • 1
  • 7
  • 2
    since the question is marked c++, i would suggest using std::vector instead. – user1810087 May 22 '14 at 14:38
  • You can probably fix it by returning `(char**)camPresets`, but please post the compilation error if you want to get a more accurate solution. – barak manos May 22 '14 at 14:40
  • What is that `DataManager`? If it's a class, you may want to make the function static. Also, using other high-level data structures would be preferred from using C-style arrays. You should add the compilation error. – E_net4 May 22 '14 at 14:41
  • 1
    `I thought I could just write 'return &camPresets;' to return the address of the array `. A `char**` is not a 2-dimensional array. That's why the compiler is giving you an error. – PaulMcKenzie May 22 '14 at 14:43
  • Yeh, I knew someone would suggest using Std::vector. The reason I'm not is because I'm coding for a micro controller, it's partly because I want to allocate an exact amount of memory, I don't want the array to grow or shrink and I don't want the overhead of string or vector. Having said that, I'm new to C++ so I may be wrong with my choice. DataManager is the class which owns the 2d array. – Rick Bush May 22 '14 at 14:45
  • 1
    @RickBush - Use `std::array`. – PaulMcKenzie May 22 '14 at 14:50
  • on a similar note .. http://stackoverflow.com/q/23416000/2567683 – Nikos Athanasiou May 22 '14 at 17:01

7 Answers7

2

The correct ugly syntax is :

char (&DataManager::getPresetsForCamera())[NO_PRESETS][PRESET_LEN]
{
    if (currentCam != cam)
        load(cam);
    return camPresets;
}

which may be simplified with a typedef:

typedef char camPresetsType[NO_PRESETS][PRESET_LEN];

camPresetsType& getPresetsForCamera();

But I really suggest to use std::array or custom class.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
0

Here you go:

char* DataManager::getPresetsForCamera(int cam)
{
    if(currentCam != cam)
        load(cam);

    return camPresets[cam];
}

Note that you should also check the bounds of that array before using it. Here's a safer version:

char* DataManager::getPresetsForCamera(unsigned int cam)
{
    assert(cam < NO_PRESETS);

    if(currentCam != cam)
        load(cam);

    return camPresets[cam];
}
0

You can dynamically allocate array for camPresets by declaring it as double pointer and return it in function

See an example

char **camPresets;

char** getPresetsForCamera(int cam);

char** getPresetsForCamera(int cam)
{
        //your validation
        return camPresets;
}

//Code to dynamically allocate memory
camPresets = (char**)malloc(NO_PRESETS* sizeof(char*)); 
    // for each row allocate Cols ints
    for (int row = 0; row < NO_PRESETS; row++) {
        camPresets[row] = (char*)malloc(PRESET_LEN* sizeof(char));
    }
shivakumar
  • 3,297
  • 19
  • 28
  • Question tagged as C++, so use `new` instead of `malloc` (if really you want to manage your memory yourself). – Jarod42 May 22 '14 at 15:47
0

Well, you need to think that a pointer and array are semantically similar, but they have different syntax.

By defining a 2d array:

char arr[W][H];

you allow the compiler to calculate the location of the element in the original block of data. Remember that the element [0][0] is basically a pointer to the begining of assigned memory block. So for example, if you defined an array and accessed:

char arr[10][20];
char arr[5][5];

You'd tell the compiler to "move 5 rows, and 5 columns from the begining", which would be simply: 5*H+5 = 5*20+5 = 105.

Now, this bracket notation is additional information for the compiler. But as you know, the array is just a block of memory. You may consider to have the same meaning:

&arr[0][0] == arr; // true, arr is "char*"

What this means, is that the pointer notation no longer provides the compiler the widths of array dimensions, and so it cannot use the index operator. The array is considered a simple continuous block of data.

In your case you should simply return a char*. You cannot return an array from the function, but you may assign it to a pointer variable.

char* newArr = fun(); // char* fun() { char* test = new char[10*20]; return test; }

To avoid possible out of range errors, use std::vector instead.

hauron
  • 4,550
  • 5
  • 35
  • 52
0

If you are concerned with using std::vector, then use std::array.

#include <array>

#define PRESET_LEN 15
#define NO_PRESETS 8

typedef std::array<char, PRESET_LEN> InnerArray;
typedef std::array<InnerArray, NO_PRESETS> Array2D;

Array2D camPresets;

Array2D getPresetsForCamera(int cam)
{
   return camPresets;
}
PaulMcKenzie
  • 34,698
  • 4
  • 24
  • 45
0

You have a number of options for returning a 2D array. One is to use a jagged array like are sort of trying to do. If you are truly using char ** as a 2D array, though, you should just stick with using it as a char ** jagged array, and not a 2D array as you are doing and why you see the compiler error.

Another option, if you insist on using true 2D arrays (they are, after all, more efficient than jagged arrays), is to just wrap the array in a struct and return the struct, like this:

struct camPresetsArray
{
    char values[NO_PRESETS][PRESET_LEN];
};

camPresetsArray DataManager::getPresetsForCamera(int cam)
{
    ...
}

Another option is to pass the return value as a function argument.

typedef char camPresetsArray[NO_PRESETS][PRESET_LEN];

void DataManager::getPresetsForCamera(camPresetsArray& outp, int cam)
{
    ...
}


camPresetsArray x;
myDataManager.getPresetsForCamera(x, y);
tenfour
  • 36,141
  • 15
  • 83
  • 142
0

Well, in the end after reading through the answers left here, I didn't want to import any libraries into my code so I stayed with a 2d array. I ended up using this code :

typedef char (*pointer_to_arrays)[PRESET_LEN];

pointer_to_arrays getPresetsForCamera(int cam);

then in the cpp

DataManager::pointer_to_arrays DataManager::getPresetsForCamera(int cam)
{
 if(currentCam != cam)
    load(cam);
 return camPresets;
}

Thanks for the pointers :P

Rick Bush
  • 81
  • 1
  • 7