1

I have a huge 2d array that I am trying to pass to a function. Here's the array:

int image[13][13] =
{
    { 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72 },
    { 72, 72, 71, 70, 70, 70, 70, 70, 70, 70, 70, 72, 72 },
    { 72, 107, 116, 145, 137, 130, 154, 118, 165, 111, 173, 116, 72 },
    { 72, 126, 150, 178, 158, 175, 163, 169, 170, 160, 176, 163, 70 },
    { 72, 130, 192, 195, 197, 186, 129, 185, 196, 196, 193, 195, 70 },
    { 72, 126, 187, 166, 85, 75, 106, 185, 191, 191, 189, 188, 69 },
    { 72, 121, 183, 111, 100, 51, 137, 188, 187, 186, 184, 180, 69 },
    { 72, 117, 177, 143, 58, 77, 137, 180, 171, 183, 178, 173, 69 },
    { 72, 111, 172, 108, 101, 110, 115, 67, 49, 120, 175, 165, 68 },
    { 72, 107, 145, 105, 145, 120, 85, 51, 51, 56, 138, 157, 68 },
    { 72, 103, 147, 158, 155, 131, 115, 114, 114, 115, 121, 152, 68 },
    { 72, 79, 146, 161, 163, 165, 168, 167, 164, 162, 158, 114, 70 },
    { 72, 69, 53, 49, 49, 49, 49, 49, 49, 49, 50, 61, 72 }
};

I have this function declared like this:

int max_2d(int p_valeurs[13][13]);

int max_2d(int p_valeurs[13][13])
{
    int valeur_max;

    for (int i = 0; i < 13; i++)
    {
        int max_local = max(p_valeurs[i], LARGEUR);

        if (valeur_max < max_local)
        {
            valeur_max = max_local;
        }
    }
    return valeur_max;
}

int max(int p_valeurs[]);

int max(int p_valeurs[], int p_taille)
{
    int valeur_max;

    for (int i = 0; i < p_taille; i++)
    {
        if (valeur_max > p_valeurs[i])
        {
            valeur_max = p_valeurs[i];
        }
    }

    return valeur_max;
}

My problem is that when I pass the image 2d array in the max_2d function, the array becomes an int(*)[13]. I don't understand what is happening and what is wrong. Can anyone help me?

EDIT

Keep in mind, this is a student work. I need to understand what's wrong and how can I fix this. Thanks!

16
  • You're passing those in by value? Yikes. You really need to read up on effectively using references. Commented Feb 1, 2015 at 19:52
  • "the array becomes an int(*)[13]" – yes, it does. That's how arrays work in C and C++ – they decay into pointers in most contexts, e. g. when you pass them to a function. Commented Feb 1, 2015 at 19:54
  • 1
    @tadman you can't just "re-cast it as int *" (even using int *p = &p_valeurs[0][0];) because that would violate the strict aliasing rule when iteration reaches the 2nd row. Commented Feb 1, 2015 at 19:55
  • 1
    @MattMcNabb What I meant is that if you have a 2D array, and you obtain a pointer to its first element (int *p = &arr[0][0]; – why would you ever do the casting thing?), then you can only use that pointer to access the elements of the first row. Anything else invokes undefined behavior (as discussed here, here and here). Commented Feb 2, 2015 at 8:54
  • 1
    @TheParamagneticCroissant those are talking about undefined behaviour due to out-of-bounds access for the array arr[0] in C. (nothing to do with strict aliasing; and also it's unclear whether it is UB in C++). However if you write int *p = (int *)&arr; or int *p = (int *)arr then there is definitely no out of bounds access because p is bounded to all of arr, not just the first row. Commented Feb 2, 2015 at 19:34

2 Answers 2

2

I see a couple of logic errors in the code:

  1. valeur_max is not initialized in those functions: this is not allowed (you cannot compare with a not-initialized value).

  2. In the second function the variable is named valeur_max but the comparison is keeping the minimum value instead (it updates valeur_max if it's bigger).

As for the title of your question in C++ arrays are implicitly converted to a pointer to the first element when passed to a function. If you really want to pass the array by value you need to wrap it up in a structure instead (note that passing by copy just to find the maximum seems a nonsense).

A 2D array is in C++ just an array of arrays, thus when passing it to a function the passed vale becomes a pointer to an array (the row). That's what int(*)[13] means... a pointer to an array of 13 integers.

For the eyes of a C++ compiler the two declarations

void foo(int x[30]);

and

void foo(int *x);

are absolutely identical (yes, the number is completely ignored).

Note that this implicit conversion (or "decay" as the standard describes it) doesn't impact element access but just the fact that the array is not copied; for example a version doing the 2d processing in just one function could be:

int max_2d(int p[13][13]) {
    int max_val = INT_MIN;
    for (int i=0; i<13; i++) {
        for (int j=0; j<13; j++) {
            if (max_val < p[i][j]) {
                max_val = p[i][j];
            }
        }
    }
    return max_val;
}
Sign up to request clarification or add additional context in comments.

3 Comments

Ok, I think I understand, but how could I access the values in the second-dimensional array in the max function?
@hsim: I'm not sure I understad the question: that code is correct (except for the mistakes I already pointed out) because the first function calls the second one to get the maximum of each row. p_valeurs is a pointer to an array in max_2d, thus p_valeurs[i] is an array that becomes a pointer to an integer when passed to max(). In that function p_valeurs[i] is an integer.
Yup, if I had to do this in one loop, I'd say what you suggest is exactly the way I would proceed. However my homework is aimed to make me work with pointers and I don't understand how I can reach the value in the array passed as pointer in the max value.
1

It's the classic problem in C and C++, where arrays cannot be passed by value. They can however be passed by reference in C++:

int max_2d(int (&p_valeurs)[13][13]);

p_valuers has the correct type. But bear in mind that this is a reference. Any changes you make, for example p_valuers[3][7]++; will be reflected at the call site.

(In C, I would pass in a pointer to the array int max_2d(int (*p_valeurs)[13][13]); for a typesafe solution.)

But this isn't a problem for you, as you are not modifying p_valuers inside the max_2d function. In fact, you should explicitly mark it as const for clarity.

int max_2d(const int (&p_valeurs)[13][13]);

Finally, I said arrays cannot be passed by value in C or C++. When you attempt to pass an array by value, it will instead pass a pointer to the first element of the array. Also, when the compiler sees arrays in the list of parameters of a function, it automatically converts the "top level" array into a pointer, int x[13][13] to int (*x)[13]. This means a function that appears to take an array actually takes a pointer. But we can block this behaviour in a number of ways, for example using a reference in C++.

Comments

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.