Error: cannot convert 'int (*)[3]' to 'int (*)[100]' for argument '1' to 'void repl(int (*)[100], int, int)'

15.2k views Asked by At

Hello im trying to write this program which replace each negative number with -1 and positive with 1 but an error :

[Error] cannot convert 'int ()[3]' to 'int ()[100]' for argument '1' to 'void replace(int (*)[100], int, int)'

what does that mean ??

#include<iostream>
using namespace std;
void replace(int Arr[][100],int rsize, int csize)
{
  for(int r=0;r<rsize;r++)
  {
    for (int c=0;c<csize;c++)
    {
      if (Arr[r][c]>0) Arr[r][c]=1;
      else if (Arr[r][c]<0) Arr[r][c]=-1;
      else Arr[r][c]=0;
    }
  }

}

int main()
{
    int a[4][3]={
    {2,0,-5},
    {-8,-9,0},
    {0,5,-6},
    {1,2,3}};

    replace(a,4,3);

    for(int i=0;i<4;i++)
      for (int j=0;j<3;j++)
        cout<<a[i][j]<<" ";}cout<<endl;

    system ("pause");
    return 0;
}
3

There are 3 answers

0
Hcorg On

You declared function void replace(int Arr[][100],int rsize, int csize) - it expects 2D array, with 'inner' dimension being 100. Then you pass to it int a[4][3] which has 'inner' dimension 3. Compiler can't convert it. Those dimensions are used to calculate memory position shift when using Arr[x][y] (it is equivalent to *(Arr + x * 100 + y). That's why compiler can't assign array with 3 to array with 100.

If you want your replace to work with any dimension change it to: void replace(int* Arr,int rsize, int csize). Then use *(Arr + r*csize + c) to access fields instead of Arr[r][c]

Even better solution: you tagged this question as C++ - use C++ library :) - std::vector<std::vector<int> > or std::array (C++11)

0
TartanLlama On

Well you declare a function which takes int[][100], then you pass it an int[4][3]. C++ doesn't work like this. In fact, you can't actually pass arrays by value at all; they decay to pointers implicitly.

If you want your function to take arbitrarily sized arrays, you could just make it take pointers to pointers instead:

void replace(int** Arr,int rsize, int csize)

Then you should throw your code away and use std::vector instead:

void replace(std::vector<std::vector<int>> &Arr)

If you want some compile-time constraints on the size of the array, you could do something like:

template <std::size_t X, std::size_t Y>
void replace (std::array<std::array<int,Y>,X>& Arr)
{
    static_assert (Y <= 100, "Inner array is too large");
}
0
AngularRat On

The issue is that you're declaring your argument (Arr[][100]) as having 100 elements. But it's not 100 elements, it's three in your code. I'm assuming what you really want is to be able to pass different sized arrays, and specify the array dimensions in the other arguments. If that's the case, you can just declare the array as an int *. So something like the following will work:

#include "stdafx.h"
#include<iostream>
using namespace std;


void replace(int *Arr, int rsize, int csize);
void print(int *Arr, int rsize, int csize);

int _tmain(int argc, _TCHAR* argv[])
{
    int a[4][3] = {
        { 2, 0, -5 },
        { -8, -9, 0 },
        { 0, 5, -6 },
        { 1, 2, 3 } };

    print((int *)a, 4, 3);


    replace((int *)a, 4, 3);
    for (int i = 0; i<4; i++)
    {
        for (int j = 0; j<3; j++)
        {
            cout << a[i][j] << " ";
        }cout << endl;
    }


    system("pause");
    return 0;
}


void replace(int *Arr, int rsize, int csize)
{
    for (int r = 0; r<rsize; r++)
    {
        for (int c = 0; c<csize; c++)
        {
            int index = (r * (rsize - 1)) + c;
            if (Arr[index] > 0)
            {
                Arr[index] = 1;
            }
            else if (Arr[index] < 0)
            {
                Arr[index] = -1;
            }
            else
            {
                Arr[index] = 0;
            }
        }
    }
}

void print(int *Arr, int rsize, int csize)
{
    char str[256];

    for (int r = 0; r<rsize; r++)
    {
        sprintf(str, "");
        for (int c = 0; c<csize; c++)
        {
            int index = (r * (rsize - 1)) + c;
            if (strlen(str) > 0)
            {
                sprintf(str, "%s, ", str);
            }
            sprintf(str, "%s%d", str, Arr[index]);
        }

        cout << str;
        cout << endl;
    }
}

Don't follow my example of using the unsafe string functions.

The reason this works is that a two-dimensional int array is just a bunch of one dimensional arrays stacked together. So an int[4][3] is just 12 ints in memory. That's functionally identical to an int[12]. If you declare the input to the function as an int *, then it's a pointer to a block of memory that contains ints, doesn't matter how many. So you can avoid the type cast errors you were getting.

There's lots of risk with doing this if you don't make sure your parameters are correct. For example, if you call the same replace function with the same input array, but claim it has 5 rows, then you'll start reading uninitialized memory. (Possibly uninitialized...more accurately, you'll at least be reading memory that is not what you think it is.) Of course, you can do the same thing without the pointer, that's the whole fun part of C++.