1

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.

Hélder Lima
  • 87
  • 1
  • 1
  • 7
  • Which line is line 5? – Ken Y-N Feb 21 '18 at 23:34
  • `*cartao2[0] = 5;` @KenY-N – Hélder Lima Feb 21 '18 at 23:40
  • what are your compiler warnings telling you?? – MFisherKDX Feb 21 '18 at 23:48
  • @MFisherKDX nothing. The program compiles. When executed through cmd it gives error, without explaining nothing more. Just the program testes7.c has stopped working (in my case it is said in portuguese). But now, with the multi-dimensional array it does not compile... – Hélder Lima Feb 22 '18 at 00:02
  • 1
    if you have other questions ask a new one, nobody will read through question1 to find that is answered and that there is a question2 buried at the end – pm100 Feb 22 '18 at 00:12
  • I agree with pm100. If you have a new question, ask a new question on a separate thread. And as for your next code: you have to pass the correct types. `cartao` is a 2-dim array, your function expects a pointer. You are passing the wrong types. – Pablo Feb 22 '18 at 00:33
  • @pm100 I agree. I can't do it now because I have no access to the computer until tomorrow. Will post it tomorrow! – Hélder Lima Feb 22 '18 at 00:38
  • @Pablo the previous one was also an array but is automatically passed as a pointer. Doesn't it work the same way to dual-dimension arrays? – Hélder Lima Feb 22 '18 at 00:39
  • Yes, the new `cartao` would decay in a `(int*)[5]`, but you the new `Mudar` expects now an `int*`, you changed the types and they don't match again. If `Mudar` were the version I posted in the answer, then `Mudar(cartao)` would work. – Pablo Feb 22 '18 at 00:45
  • @Pablo I see. I will test it tomorrow. Any tips of where to read more about pointers? – Hélder Lima Feb 22 '18 at 00:54
  • The C book you are reading? I don't know, I haven't read a C book for a long time, so I'm not up to date with which book is good. See https://stackoverflow.com/questions/562303/the-definitive-c-book-guide-and-list – Pablo Feb 22 '18 at 00:56
  • @Pablo A notebook from the teacher of my course. – Hélder Lima Feb 22 '18 at 00:59

3 Answers3

3

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.

Pablo
  • 13,271
  • 4
  • 39
  • 59
  • Thank you very much @Pablo for this answer! What program do you use to get that errors pointed? Would you be able to help with the multidimensional arrays? – Hélder Lima Feb 22 '18 at 00:15
  • +1, You beat me by a couple minutes. I'll delete my answer shortly as there is no additional information there. – MFisherKDX Feb 22 '18 at 00:19
  • I use valgrind to detect leaks and improper access to arrays and memory and gdb to debug when I want to step through the code. – Pablo Feb 22 '18 at 00:19
2

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};
Stephen Docy
  • 4,738
  • 7
  • 18
  • 31
0

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;
bbcbbc1
  • 95
  • 7