The compiler adjusts parameters having array types to pointers to array element types.
So these function declarations
void changeelement(char p[100] );
void changeelement(char p[10] );
void changeelement(char p[] );
and
void changeelement(char *p );
are equivalent and declare the same one function.
From the C Standard (6.7.6.3 Function declarators (including prototypes))
7 A declaration of a parameter as ‘‘array of type’’ shall be
adjusted to ‘‘qualified pointer to type’’, where the type qualifiers
(if any) are those specified within the [ and ] of the array type
derivation. If the keyword static also appears within the [ and ] of
the array type derivation, then for each call to the function, the
value of the corresponding actual argument shall provide access to the
first element of an array with at least as many elements as specified
by the size expression.
You may write for example in the same program
void changeelement( char *p );
void changeelement( char p[] )
{
p[0] = 'v';
}
On the other hand, an array used as an argument expression is implicitly converted to pointer to its first element.
From the C Standard (6.3.2.1 Lvalues, arrays, and function designators)
3 Except when it is the operand of the sizeof operator or the unary &
operator, or is a string literal used to initialize an array, an
expression that has type ‘‘array of type’’ is converted to an
expression with type ‘‘pointer to type’’ that points to the initial
element of the array object and is not an lvalue. If the array
object has register storage class, the behavior is undefined.
In C passing an object by reference means passing the object indirectly through a pointer to it. From the C Standard: "A pointer type describes an object whose value provides a reference
to an entity of the referenced type." Thus dereferencing the pointer the function has a direct access to the object pointed to by the pointer and can change it.
For example
#include <stdio.h>
void f( int *p )
{
*p = 10;
}
int main( void )
{
int x = 0;
f( &x );
printf( "x = %d\n", x );
}
The program output is
x = 10
Similarly when a function deals with a pointer to the first element of an array then using the pointer arithmetic and dereferencing the pointer the function can change any element of the array.
By the way the above function may be rewritten like
void f( int p[] )
{
p[0] = 10;
}
though the argument expression does not use an array. In any case even you use an array as an argument expression it is implicit;y converted to a pointer to a single element: the first element of the array.