0

I'm quite new to VC++, and I need to pass 4 arrays between functions, so I'm using another array to store their pointers. Have I done it correctly?

unsigned int* step1(...) {

    ...

    // save data arrays
    unsigned int* savedData = new unsigned int[4];
    savedData[0] = *data0;
    savedData[1] = *data1;
    savedData[2] = *data2;
    savedData[3] = *data3;
    return savedData;
}

unsigned char* step2(unsigned int* savedData, ...) {

    // read data arrays
    unsigned int* data0 = &savedData[0]; 
    unsigned int* data1 = &savedData[1];
    unsigned int* data2 = &savedData[2]; 
    unsigned int* data3 = &savedData[3];

    ...

}
Kevin Boyd
  • 12,121
  • 28
  • 86
  • 128

5 Answers5

3

In order to complete the previous valid answers, I will try to expand the answer:

Have I done it correctly?

Well, in order to pass data between functions: yes, doing it with pointers is an option. But it is commonly discouraged by the community because it makes troublesome the memory management.

When you work with pointers pointing dynamic memory, you must have a clear image of WHERE the memory is created and WHERE the memory will be deleted, in other words: the cycle of life of the memory must be clear and straightforward and for this reason, pass pointers between functions is commonly discouraged.

For example, in your case: the unsigned int* step1(...) function returns a pointer but looking at it, a new programmer or someone that works with you wouldn't tell if the pointer returned is dynamic memory and if calling step1 must delete or delete [] the memory after the call, same goes for unsigned char* step2(unsigned int* savedData, ...) and would be more confusing and troublesome because someone would ask: step2 would alter the savedData passed?

In order to fix the step2 issue, you can change the function to:

unsigned char* step2(const unsigned int* const savedData, ...)

By adding the const you're telling: "Hey! step2 isn't going to alter the contents of savedData nor changing the address it is pointing to".

But all the previous text is useless because doesn't fix the most important problem: Where the memory is freed?

In the step1 you're creating memory dynamically, in the step2 this memory is readed but... the delete is hidden somewhere in the code that you don't paste? or there is a step3 waiting for take care of the memory?

To avoid all this memory headaches, is commonly advised the use of STL containers, like std::vector, the container will take care of the memory management for you, in your case:

typedef std::vector<int> intvector;
typedef std::vector<intvector> intintvector;

void step1(intintvector &Data, ...) {
    ...
    // create data arrays
    intvector data0, data1, data2, data3;
    // fill data0, data1, data2, data3
    // ...
    // save data arrays.
    Data.push_back(data0);
    Data.push_back(data1);
    Data.push_back(data2);
    Data.push_back(data3);
}

void step2(const intintvector &savedData, ...) {

    // read data arrays
    intvector data0 = savedData[0]; 
    intvector data1 = savedData[1];
    intvector data2 = savedData[2]; 
    intvector data3 = savedData[3];
    // ...
}

In brief summary: You aren't using correctly the pointer part if you don't take care of the dynamic memory, so, you must fix this issue or delegate into STL containers.

Hope it helps! :D

PaperBirdMaster
  • 12,806
  • 9
  • 48
  • 94
1

Use std::vector.

std::vector<int> data;
data.push_back(data0);
data.push_back(data1);
data.push_back(data2);
data.push_back(data3);

And

int data0 = data[0];
int data1 = data[1];
int data2 = data[2];
int data3 = data[3];

And add some code, where these functions will be used.

kuperspb
  • 339
  • 2
  • 10
1

You will need an array of pointers, for example:

//The function that takes the array
void foo( char ** data )
{
    std::cout << data[0];
    std::cout << data[1];
    std::cout << data[2];
}

main()
{
    char * str = "aaa";
    char * str1 = "sss";
    char * str2 = "ddd";
    char ** res = new char *[3];//here's your array that has 3 elements each of which is a pointer.
    res[0]=str;
    res[1]=str1;
    res[2]=str2;
    foo( res );
    return 0;
}

The output will be

aaasssddd

A slightly better way:

It would be better to use stl containers instead of raw pointers since they are easier and safer to use. With pointers, it will work the same way:

void foo( std::vector< char * >vec )
{
    std::cout << vec[0];
    std::cout << vec[1];
    std::cout << vec[2];
}

main()
{
    char * str = "aaa";
    char * str1 = "sss";
    char * str2 = "ddd";
    std::vector< char * >vec;
    vec.push_back(str);
    vec.push_back(str1);
    vec.push_back(str2);

    foo( vec );
return 0;
}

A further improved way:

And finally, the best way is to use strings:

void foo( std::vector< std::string >vec )
{
    std::cout << vec[0];
    std::cout << vec[1];
    std::cout << vec[2];
}

main()
{
    std::string str = "aaa";
    std::string str1 = "sss";
    std::string str2 = "ddd";
    std::vector< std::string >vec;
    vec.push_back(str);
    vec.push_back(str1);
    vec.push_back(str2);

    foo( vec );
return 0;
}
SingerOfTheFall
  • 29,228
  • 8
  • 68
  • 105
1

Assuming you really want what you've written in question (4 arrays grouped into one), first of all you need 4 arrays, for example int:

int data1[] = {1,2,3,4};
int data2[] = {5,6,7,8,9,10};
int *data3; // Let's say those two were allocated by malloc/new
int *data4;

// Now array that will contain those values
int **data = new (int*)[4]; // int * = your datatype (array of ints)
                            // (int*)[] = array of arrays of ints
data[0] = data1;
data[1] = data2;
data[2] = data3;
data[3] = data4;


// And reverse function
data1 = data[0];
data2 = data[1];
data3 = data[2];
data4 = data[3];

Few notes:

  • if you want to have those "arrays" resizeable use (or use more than 4 items after time) use std::vector or another STL Container
  • if those data chucks have any special meaning (like data1 = user ids, data2 = visitor ids, ...) build class or structure that will name them:

    // In C:
    struct user_data{
       int *user_ids;
       int *visitor_ids;
       char **unregistered_user_names; // Feel free to use another types
    }
    
    // In C++
    class UserData {
        std::vector<int> userIds;
        std::vector<int> visitorIds;
        std::vector<std::string> unregisteredUserNames;
     }
    
  • Once allocated data with new unsigned int [4] don't forget free memory with delete [] array

Vyktor
  • 20,559
  • 6
  • 64
  • 96
  • Your first example does not compile in VS2010. Is says "C2440: '=' : cannot convert from 'int *' to 'int'" – Kevin Boyd Oct 25 '12 at 06:51
  • And I need the data array to be dynamically allocated so it does not get GC'd after the function exits. – Kevin Boyd Oct 25 '12 at 06:53
  • Your example still does not compile in VS2010, it says "Error: type name is now allowed". The error is at the line `new (*int)` – Kevin Boyd Oct 25 '12 at 08:38
  • @KevinBoyd ah `*` on wrong side of `int`, it should be `(int*)`, try it that way – Vyktor Oct 25 '12 at 08:44
0

I tried Vyktor's solution but it didn't work. I finally got it working using plain ol' arrays (no STL/vectors) and using the following code to save/load arrays from another parent array.

Note that this approach is considered "legacy" since you have to unallocate the arrays manually using the delete [] myArray syntax.

unsigned int** step1(...) {

    ...

    // save data arrays
    unsigned int** savedData = new unsigned int*[4]; // ** means pointer to a pointer
    savedData[0] = data0; // transfer the pointer value straight
    savedData[1] = data1;
    savedData[2] = data2;
    savedData[3] = data3;
    return savedData;
}

unsigned char* step2(unsigned int** savedData, ...) { /// input is pointer to pointer

    // read data arrays
    unsigned int* data0 = savedData[0]; // read pointer straight
    unsigned int* data1 = savedData[1];
    unsigned int* data2 = savedData[2]; 
    unsigned int* data3 = savedData[3];

    ...

}
Kevin Boyd
  • 12,121
  • 28
  • 86
  • 128