3

I'm learning C, and I was just curious as to why C functions, when given arguments like int, char, double etc., don't change the values of those arguments when called, but when they are passed array arguments, they do alter array elements.

For example:

void conversion(int array[])
{
    array[0] = 0;
}

void numeric(int m)
{
    m = 0;
}

When you declare and initialize int array[1] = {1} and int m = 1, call the functions with these arguments, the array[0] gets changed, but the int m does not. Is there a reason that array arguments are changed, but int arguments remain the same? Is it something to do with pointers?

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
Harambe17
  • 175
  • 7

3 Answers3

3

C uses pass by value for function argument passing, so for non-array type variables, the values cannot be modified from the called function. Inside the called function, it receives a copy of the actual argument being passed, so any changes made to the called function parameter does not reflect back to the caller argument.

However, while passing an array to a function, it decays to the pointer to the first element of the array, and the content pointed to by that pointer can be modified from the called function. That is why, in your case, changes to array[0] is reflected back to the caller, but any attempted change to array itself won't be persisting, as array itself is passed by value.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
3

Instead of this function

void numeric(int m)
{
    m = 0;
}

consider the following code snippet

void numeric(int *m_ptr)
{
    *m_ptr = 0;
}

//...

int m = 1;

numeric( &m );

As you can see the variable m will be changed in the function.

Now let's use the same function with an array

int m[1] = 1;

numeric( &m[0] );

And in this case the object m[0] will be changed in the function.

Now this function

void numeric(int *m_ptr)
{
    *m_ptr = 0;
}

can be rewritten like

void numeric(int m_ptr[])
{
    *m_ptr = 0;
}

because a parameter declared as having an array type is adjusted to pointer. For example these function declarations

void numeric(int m_ptr[1]);
void numeric(int m_ptr[10]);
void numeric(int m_ptr[100]);
void numeric(int m_ptr[]);

are equivalent each other and in turn are equivalent to the function declaration

void numeric(int *m_ptr);

and declare the same one function. You may include all these declaration in one compilation unit.

On the other hand an array passed to a function is implicitly converted to pointer to its first element. So the call of the function above

numeric( &m[0] );

is equivalent to the call

numeric( m );

Thus then array is used as a parameter and correspondingly as an argument its element can be changed because the elements passed to the function by reference. If you will pass a single object by reference as it is shown in the first code snippet example above then it will be also changed.

So the difference exists between whether a function accepts an argument by reference or by value. In case when arrays are used then their elements in fact are passed to functions by reference and hence can be changed in the function.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

Arrays decay into pointers, when passed to functions. You don't change the array, but the contents of the array.

These two functions are equivalent:

int foo(int arr[]);

int bar(int *arr);

The unofficial C-FAQ has more information on how arrays and pointers are different and/or similar: http://c-faq.com/aryptr/

There are many subtle differences.

Leandros
  • 16,805
  • 9
  • 69
  • 108
  • `Arrays decay into pointers`.. without proper context, this is wrong. example: `sizeof` operator. – Sourav Ghosh Jan 30 '17 at 11:23
  • @SouravGhosh Correct. Arrays decay into pointers, when passed to a function. – Leandros Jan 30 '17 at 11:25
  • 2
    @Leandros - not only when passed to functions, but mostly in general. The exceptions for when it doesn't happen are few (and `sizeof` is among them). – StoryTeller - Unslander Monica Jan 30 '17 at 11:29
  • @StoryTeller Yes, there are many subtle differences. It's enough for this answer to know that they're decaying into pointers when passed to a function. Even this has different catches. – Leandros Jan 30 '17 at 13:07