Asked  7 Months ago    Answers:  5   Viewed   54 times

I wrote a function containing array as argument, and call it by passing value of array as follows.

void arraytest(int a[])
{
    // changed the array a
    a[0]=a[0]+a[1];
    a[1]=a[0]-a[1];
    a[0]=a[0]-a[1];
}

void main()
{
    int arr[]={1,2};
    printf("%d t %d",arr[0],arr[1]);
    arraytest(arr);
    printf("n After calling fun arr contains: %dt %d",arr[0],arr[1]);
}

What I found is though I am calling arraytest() function by passing values, the original copy of int arr[] is changed.

Can you please explain why?

 Answers

95

When passing an array as a parameter, this

void arraytest(int a[])

means exactly the same as

void arraytest(int *a)

so you are modifying the values in main.

For historical reasons, arrays are not first class citizens and cannot be passed by value.

Tuesday, June 1, 2021
 
Gigamegs
answered 7 Months ago
61

You cannot do it that way. When you pass an array to a function, it decays into a pointer to the first element, at which point knowledge of its size is lost.

If you want to know the size of an array passed to the function, you need to work it out before decay and pass that information with the array, something like:

void function (size_t sz, int *arr) { ... }
:
{
    int x[20];
    function (sizeof(x)/sizeof(*x), x);
}
Thursday, June 17, 2021
 
Dev
answered 6 Months ago
Dev
28

The warning is exactly right. Your function wants an array of pointers. You're giving it an array of arrays.

Expected:

 sep_foo:
 +------+       +-----+
 |char**|--> 0: |char*|-->"string1"
 +------+       +-----+
             1: |char*|-->"string2"
                +-----+
*sep_foo_qty-1: |...  |
                +-----+

What you provided:

           sep_foo:
           +--------------------------------+
        0: | char[MAX_STRING_LENGTH]        |
           +--------------------------------+
        1: | char[MAX_STRING_LENGTH]        |
           +--------------------------------+
MAX_QTY-1: | ...                            |
           +--------------------------------+

An array with elements of type X can "decay" into a pointer-to-X, or X*. But the value of X isn't allowed to change in that conversion. Only one decay operation is allowed. You'd need it to happen twice. In your case, X is array-of-MAX_STRING_LENGTH-chars. The function wants X to be pointer-to-char. Since those aren't the same, the compiler warns you. I'm a bit surprised it was just a warning since nothing good can come from what the compiler allowed to happen.

In your function, you could write this code:

char* y = NULL;
*sep_foo = y;

That's legal code since sep_foo is a char**, so *sep_foo is a char*, and so is y; you can assign them. But with what you tried to do, *sep_foo wouldn't really be a char*; it would be pointing to an array of char. Your code, in effect, would be attempting to do this:

char destination[MAX_STRING_LENGTH];
char* y = NULL;
destination = y;

You can't assign a pointer into an array, and so the compiler warns that the call is no good.

There are two ways to solve this:

  • Change the way you declare and allocate sep_foo on the calling side so it matches what the function expects to receive:

    char** sep_foo = calloc(MAX_QTY, sizeof(char*));
    for (int i = 0; i < MAX_QTY; ++i)
      sep_foo[i] = malloc(MAX_STRING_LENGTH);
    

    or, equivalently

    char* sep_foo[MAX_QTY];
    for (int i = 0; i < MAX_QTY; ++i)
      sep_foo[i] = malloc(MAX_STRING_LENGTH);
    
  • Change the prototype of the function to accept what you're really giving it:

    int parse(const char *foo, char sep_foo[MAX_QTY][MAX_STRING_LENGTH], int *sep_foo_qty);
    
Wednesday, July 28, 2021
 
elias
answered 5 Months ago
41

I would write this as:

- (void) testCall: (int *) aMatrice;

Doing so allows you to avoid multiple mallocs and the math to calculate a single offset in a linear array based on x, y coordinates in a 2D array is trivial. It also avoids the multiple mallocs implied by int** and the limitations of 2D array syntax perpetuated by the language.

So, if you wanted a 4x5 array, you might do:

#define WIDTH 4
#define HEIGHT 5
#define INDEXOF(x,y) ((y*WIDTH) + x)

int *myArray = malloc(sizeof(int) * 5 * ELEMS_PER_ROW);

You could then initialize the array linearly or with a nested for loop:

for(int x=0; x<width; x++)
    for(int y=0; y<height; y++)
        myArray[INDEXOF(x,y)] = ... some value ...;

And you would pass it to the method like:

[foo testCall: myArray];

Though you might want to also carry along the width and the height or, better yet, create a IntMatrix subclass of NSObject that wraps all of the pointer arithmetic and storage beyond a nice clean API.

(all code typed into SO)

Monday, August 16, 2021
 
Andres
answered 4 Months ago
42

You're resizing the vectors incorrectly. For example:

for(int j=0;j<max_rows;++j)
{
  Triangle[i].resize(j+1);
}

You are resizing Triangle[i] multiple times here. Probably you meant to say

for(int j=0;j<max_rows;++j)
{
  Triangle[j].resize(j+1);
}
Thursday, December 2, 2021
 
Anders Brohäll
answered 4 Days ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share