At the level of bits in the computer, arguments can only be passed by value. Bits representing some argument are written to a processor register or memory location designated as the place to pass an argument. Passing by reference is a construct built upon passing by value by using an address as the value that is passed. Passing an address can be implemented automatically or manually. Both methods are pass-by-reference.
When we pass some entity by passing its address instead of passing its value directly, that is called pass by reference. This terminology long antedates the creation of “references” in C++. In assembly language, when we load the address of some thing into a register to pass it to a function, that was, and is, called pass by reference. The C standard specifies a pointer provides a reference to an entity (C 2018 6.2.5 20). So, when we have a pointer to an object, we have a reference to an object, and when we pass the pointer to a function, we are passing a reference to the object to the function.
Some languages automated pass-by-reference. FORTRAN passes everything by reference except for some special syntax for calling routines outside FORTRAN. However, whether passing-by-reference is implemented as an automatic feature of the programming language, by a programmer manually loading an address in assembly language, or by a programmer manually requesting an address with a language operator such as C’s &
, when a reference to an object is passed, then the object is passed by reference.
C++ created a new type that it called a “reference,” but this was a new use of the word. The C++ meaning of “reference” applies to C++ only. It does not change the existing use of that word outside the context of C++. Outside of C++, “reference” has its ordinary English meaning of providing information on another thing.
Regarding your specific question about passing an array in C,
in C, an array argument is automatically converted to the address of its first element, and this address is typically used to access the entire array. So the array is in fact passed by reference. Describing this as an automatic conversion to a pointer is merely documenting the details. The effect is the same: The function is given access to the object the caller designated by providing a reference to it.
Further, any dispute over the meaning of “pass by reference” is merely one about terminology, not about the actual mechanisms used in the computer.