Rick Bush
Rick Bush

Reputation: 81

C++ Return pointer to 2d array of chars

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.

Upvotes: 2

Views: 892

Answers (7)

Rick Bush
Rick Bush

Reputation: 81

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

Upvotes: 0

Jarod42
Jarod42

Reputation: 218098

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.

Upvotes: 2

tenfour
tenfour

Reputation: 36896

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);

Upvotes: 0

PaulMcKenzie
PaulMcKenzie

Reputation: 35454

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;
}

Upvotes: 0

hauron
hauron

Reputation: 4668

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.

Upvotes: 0

shivakumar
shivakumar

Reputation: 3407

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));
    }

Upvotes: 0

disconnectionist
disconnectionist

Reputation: 508

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];
}

Upvotes: 0

Related Questions