Указатель массива C ++ в параметрах функций - PullRequest
2 голосов
/ 23 марта 2020

Может кто-нибудь объяснить мне, как / почему эти функции одинаковы?

void doubleArray(int* values, int length)

void doubleArray(int values[], int length)

Мне не нужно было ничего менять, чтобы мой код продолжал работать точно так же, но я не уверен в логике c. Я ожидал, что придется как минимум изменить то, что было написано в функции. Полный код ниже, если необходимо;

  #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;
    }
}

Ответы [ 3 ]

3 голосов
/ 23 марта 2020

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

Тип каждого функционального параметра в списке параметров определяется в соответствии со следующими правилами:

[.. ]

2) Если типом является «массив T» или «массив неизвестной границы T», он заменяется типом «указатель на T»

[..]

Из-за этих правил следующие объявления функций объявляют точно такую ​​же функцию:

int f(char[]);
int f(char* s);
int f(char* const);
int f(char* volatile s);
1 голос
/ 23 марта 2020

Почему они одинаковые? Потому что это правила C ++ (которые он унаследовал от C).

Разработчики C сочли плохой идеей возможность передавать массив в функцию. Они чувствовали, что предпочтительнее вместо этого передать указатель на первый элемент массива. Сомнительно (на мой взгляд).

Но они также решили, что не хотят отказываться от синтаксиса массива в объявлении параметра функции. Поэтому они решили, что при использовании в качестве параметра функции форма массива T param[] представляет собой просто другой способ записи формы указателя, T* param. Это то же самое, если указать размер для массива (который игнорируется), T param[10] также является указателем. Еще более сомнительно (на мой взгляд).

В C ++ вы можете избежать всего этого, используя std::vector или std::array. В C тебе не так везет.

0 голосов
/ 23 марта 2020

Предположим, мы объявляем массив int:

int values[10];

В стеке выделен блок памяти на 10 дюймов, а переменная values содержит адрес начала этого блока. памяти, или, другими словами, адрес нулевого элемента массива, который является одним и тем же.

Таким образом,

&values[0] == values

всегда верно.

Аналогично, эти два оператора обращаются к одному и тому же элементу

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

Таким образом, если у нас есть параметр функции (или любая другая переменная), он может быть объявлен как тип int* или int[] и оба примет values, потому что оба объявления - просто альтернативные способы объявления одного и того же - указателя. .

Это может вызвать путаницу, поскольку оба эти вызова к foo() являются действительными:

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

Так что для стиля, если функция ожидает массив, она должна принять массив для (int[]) и длина. Если он ожидает один объект, он должен взять указатель (int*).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...