简体   繁体   中英

C++ Array Pointer in Function Parameters

Can someone please explain to me how/why these functions are the same?

void doubleArray(int* values, int length)

void doubleArray(int values[], int length)

I didn't have to change anything for my code to still work completely the same, but I'm not sure of the logic. I expected to have to change what was written in the function at the very least. Full code is below if needed;

  #include <iostream>

    using std::cout;
    using std::endl;

void doubleArray(int* values, int length);

int main() {

    int length = 10;
    int values[length];

    for (int i = 0; i < length; i++){
        values[i] = i;
    }

    doubleArray(values, length);

    for (int i = 0; i < length; i++) {
      cout << values[i] << endl;
   }

}

void doubleArray(int* values, int length) {
    for(int i = 0; i < length; i++){
        values[i] = values[i] * 2;
    }
}

From https://en.cppreference.com/w/cpp/language/function#Parameter_list :

The type of each function parameter in the parameter list is determined according to the following rules:

[..]

2) If the type is "array of T" or "array of unknown bound of T", it is replaced by the type "pointer to T"

[..]

Because of these rules, the following function declarations declare exactly the same function:

 int f(char[]); int f(char* s); int f(char* const); int f(char* volatile s);

Why are they the same? Because that's the rules of C++ (which it inherited from C).

The designers of C felt it was a bad idea to be able to pass an array to a function. They felt that it was preferable to pass a pointer to the array's first element instead. Questionable (in my view).

But they also decided they didn't want to do away with the array syntax in a function parameter declaration. So they decided that, when used as a function parameter, the array form T param[] was just a different way of writing the pointer form, T* param . It's even the same if you specify a size for the array (which is ignored), T param[10] is also a pointer. Even more questionable (in my view).

In C++ you are able to avoid all this by using std::vector or std::array . In C you are not so lucky.

Suppose we declare an array of int :

int values[10];

A block of memory for 10 ints is allocated on the stack, and the variable values contains the address of the beginning of that block of memory, or to put it another way, the address of the zeroth element of the array, which is the same thing.

Thus

&values[0] == values

is always true.

Similarly these two statements are addressing the same element

cout << values[5];
cout << *(values + 5);

Thus if we have a function parameter (or any other variable), it can be declared as of type int* or int[] and both will accept values , because both declarations are merely alternative ways of declaring the same thing - a pointer. .

This can cause confusion, since both of these calls to foo() are valid:

void foo (int[] vals);

int values[10];
foo (values); // Passing an array

int x = 0;
int* px = &x:
foo (px);     // Passing a single object by address

So as a matter of style, if a function expects an array, it should take the array for ( int[] ) and a length. If it expects a single object it should take a pointer ( int* ).

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