Q: Changing a value in an int array in c I am trying to understand the values/pointers management in arrays.
Imagine an array of 5 elements and altering them from a function outside main. I have to use pointers. I have made this simple program to try to execute it:
#include <stdio.h>

void Mudar (int **cartao2)
{
    *cartao2[0] = 5;
    *cartao2[1] = 4;
    *cartao2[2] = 3;
    *cartao2[3] = 2;
    *cartao2[4] = 1;
}

int main()
{
    int cartao[] = {1,2,3,4,5};

    printf("int cartao[] = {");
    for (int i = 0; i < 4; i++)
        printf("%d,", cartao[i]);
    printf("%d};\n",cartao[4]);

    Mudar(&cartao);

    printf("int cartao[] = {");
    for (int i = 0; i < 4; i++)
        printf("%d,", cartao[i]);
    printf("%d};\n",cartao[4]);

}

This program gives error while executing but only when trying to execute line 5. It even prints
int cartao[] = {1,2,3,4,5};

What is wrong here.
The next step is trying to change a value inside an array of arrays. Any tips to achieve that?
EDIT
As @Stephen Docy point this code now works
#include <stdio.h>

void Mudar (int *cartao2)
{
    cartao2[0] = 5;
    cartao2[1] = 4;
    cartao2[2] = 3;
    cartao2[3] = 2;
    cartao2[4] = 1;
}

int main()
{
    int cartao[] = {1,2,3,4,5};

    printf("int cartao[] = {");
    for (int i = 0; i < 4; i++)
        printf("%d,", cartao[i]);
    printf("%d};\n",cartao[4]);

    Mudar(cartao);

    printf("int cartao[] = {");
    for (int i = 0; i < 4; i++)
        printf("%d,", cartao[i]);
    printf("%d};\n",cartao[4]);

}

And the output is
int cartao[] = {1,2,3,4,5}; int cartao[] = {5,4,3,2,1};

But now I'm curious should't this work the same way?
#include <stdio.h>

void Mudar (int *cartao2)
{
    int aux = 25;
    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 5; j++)
        {
            cartao2[i][j] = aux;
            aux--;
        }
    }
}

int main()
{
    int cartao[5][5];
    int aux = 1;

    //populates cartao from 1 to 25
    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 5; j++)
        {
            cartao[i][j] = aux;
            aux++;
        }
    }

    //prints before changing
    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 5; j++)
        {
            printf("%2d ", cartao[i][j]);
        }
        printf("\n");
    }

    Mudar(cartao);

    //prints after changing
    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 5; j++)
        {
            printf("%2d ", cartao[i][j]);
        }
        printf("\n");
    }

}

Because the program doesn't even compile:
testes7.c:10: error: pointer expected

But it is used the same way as the code that now works well.

A: Stephen Docy gave you a solution as to how to pass an array to a function. I'd
like to comment on the way you did and why it fails.
int cartao[] = {1,2,3,4,5};

This creates an int[5] array. &array has the type int (*)[5], which is a
pointer to an int[5] array.
Your function a double pointer int **cartao2. This type is not the same as
int (*)[5], your compiler should have warned you about this with
a.c:21:11: warning: passing argument 1 of 'Mudar' from incompatible pointer type [-Wincompatible-pointer-types]
     Mudar(&cartao);
           ^
a.c:3:6: note: expected 'int **' but argument is of type 'int (*)[5]'
 void Mudar (int **cartao2)
      ^~~~~

Mudar sees a double pointer and when you do
*cartao2[2] = 3;

you are doing cartao2[2][0] = 3, but because you didn't pass the correct type,
you are dereferencing at the incorrect position in memory and writing where you shouldn't. You would have to write your
function like this:
void Mudar (int (*cartao2)[5])
{
    cartao2[0][0] = 5; // or (*cartao2)[0] = 5;
    cartao2[0][1] = 4; // or (*cartao2)[1] = 4;
    cartao2[0][2] = 3; // or (*cartao2)[2] = 3;
    cartao2[0][3] = 2; // or (*cartao2)[3] = 2;
    cartao2[0][4] = 1; // or (*cartao2)[4] = 1;
}

In this case the function expects a pointer to int[5]. Note that if you
declare it to accept a pointer to an array of any size, you would have to
declare it as
void Mudar(int (*cartao2)[], size_t len)
{
    for(size_t i = 0; i < len; ++i)
        (*cartao2)[i] = 10*i;
}

In this case you cannot use the notation cartao2[0][i], because the compiler
doesn't know the real size of the array, however (*cartao2)[i] works.

A: Unlike simple, scalar variables like int, arrays get passed as pointers, so you don't need to pass in the address of cartao in order to update its contents.  Now if you wanted to change what memory block cartao was pointing to, then you would need to pass in its address.
void Mudar(int *cartao2)
{
    cartao2[0] = 5;
    cartao2[1] = 4;
    cartao2[2] = 3;
    cartao2[3] = 2;
    cartao2[4] = 1;
}

Mudar(cartao);

output :
int cartao[] = {1,2,3,4,5};
int cartao[] = {5,4,3,2,1};


A: For 2D array ,try this . M is rows ,n is columns.
In mudar function .
 for (i = 0; i < m; i++)
  for (j = 0; j < n; j++)
    *((arr+i*n) + j) =aux;

