简体   繁体   中英

Why do C Functions Alter Arrays Automatically?

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?

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.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM