dream_koala21
dream_koala21

Reputation: 23

Trouble working with 2d array passed by reference C

So I am working on an assignment and I am having trouble figuring out how to use this 2d array which was passed by reference.

What I am given is this

int main(){
//cap and flow initialized 
maximum_flow(1000, &(cap[0][0]), &(flow[0][0]));

}

So I wanted to copy the contents of cap over to another 2d array I dynamically allocated, but after hitting an error I decided to print out the values I have in cap2 and capacity, I'm not getting back all the values that I should.

void maximum_flow(int n, int *capacity, int *flow){
    int **cap2;
    cap2 = (int**) malloc(sizeof(int *)*n);
    for (i = 0; i < n; i++)
    {
      cap2[i] = (int*) malloc(sizeof(int)*n);
    }

    for (i = 0; i < n; i++)
    {
        for (j = 0; j < n; j++)
        {   
          cap2[i][j] = (*(capacity + i*n + j));
          (*(flow + i*n + j)) = 0;
        }
    }
}

Upvotes: 0

Views: 78

Answers (1)

John Bode
John Bode

Reputation: 123448

This isn't going to be a terribly useful answer, since your code doesn't actually show the problem described; based on what's presented, I see no obvious reason why cap and cap2 shouldn't have the same contents by the end of the maximum_flow function. But I'd like to offer some background and a suggestion.

I'm going to assume cap and flow are declared as n by n arrays of int in main, where n is known at compile time.

The reason your instructor is using this interface is that passing multidimensional arrays as function arguments is problematic in C. Remember that unless it's the operand of the sizeof or unary & operators, or is a string literal being used to initialize another array in a declaraiton, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array.

So, assuming a declaration like

int cap[10][10];
int flow[10][10];

the expressions cap and flow will each "decay" to type int (*)[10] (pointer to 10-element array of int). So if you wrote your function call as

maximum_flow( 1000, cap, flow );

then the function definition would have to be written as

void maximum_flow( int n, int (*cap)[10], int (*flow)[10] ) { ... }

or

void maximum_flow( int n, int cap[][10], int flow[][10] ) { ... }

In the context of a function parameter declaration, T a[][N] and T (*a)[N] mean the same thing.

The size of the outer dimension has to be specified in the array pointer declaration, and the problem is that a pointer to a 10-element array is a different, incompatible type from a pointer to an any-value-other-than-10-element array; thus, maximum_flow could only ever be used for N x 10-element arrays, limiting its usefulness. One way around this problem is to have the function receive an explicit pointer to the first element, and treat that pointer as a 1D array of size N * M.

Long story short, since you're treating your input parameters as 1D arrays, you are probably better off creating cap2 as a 1D array as well:

int *cap2 = malloc( sizeof *cap2 * n * n );
...
cap2[i * n + j] = capacity[i * n + j]; // use array subscript notation instead
flow[i * n + j] = 0;                   // of explicit dereferences

From the code you've posted, it's not clear what maximum_flow is supposed to do, nor why you need cap2. Note also that at some point you need to free the memory allocated to cap2, otherwise you have a memory leak.

If you're using a C99 or later compiler, you should be able to use a variable-length array instead of malloc:

int cap2[n * n]; // or int cap2[n][n], but like I said above, if you're 
                 // treating your inputs as 1D arrays, you should also treat
                 // cap2 as a 1D array. 

The advantage of a VLA is that you don't need to know the size at compile time, and it's treated like any other auto variable, meaning the memory for it will be released when the function exits.

The disadvantage of a VLA is that you can't use it as anything but a local variable; you can't have a VLA as a struct or union member, nor can you declare one static or at file scope. Neither can you explicitly initialize a VLA.

Upvotes: 1

Related Questions