Неожиданные результаты при передаче массивов в качестве параметров в C? - PullRequest
2 голосов
/ 07 января 2020

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

void f(int *b)
{
  b[2]=1;
}

in main:
f(validArray);

Однако, даже если мы передаем указатель, это не кажется на работу;

void foo(int *b)
{
  b=b+2;
}

in main:
f(validArray);

не перемещает указатель на шаг вперед. Почему это так?

Ответы [ 3 ]

2 голосов
/ 07 января 2020
b[2]=1;

по существу

*(b+2) = 1;

, что означает изменение данных в адресе (b+2)


b=b+2;

это означает, что вы ставите b точку до 2 элементов рядом с тем, на что ранее указывал b, что не влияет на данные в адресе указателя b, следовательно, не изменяет данные в массиве validArray

2 голосов
/ 07 января 2020

Для начала массивы являются немодифицируемыми l-значениями. Так что вы не можете писать, например,

validArray = validArray + 2;

Что касается этого фрагмента псевдокода

void foo(int *b)
{
    b=b+2;
}

in main:
foo(validArray);

, тогда указатель b является локальной переменной функции. Таким образом, в функции значение b изменяется из-за этого оператора

    b=b+2;

Но это не влияет на переданный аргумент.

Вместо этого вы можете написать

void foo( int **b )
{
    *b = *b + 2;
}

int main( void )
{
    int validArray[] = { 1, 2, 3, 4, 5 };

    int *p = validArray;
    foo( &p );
    printf( "%d\n", *p );
}

В C термин «передача по ссылке» означает косвенную передачу объекта через указатель на него. Таким образом, разыменовывая указатель в функции, вы можете изменить указанный объект. Указатели - это одни и те же объекты. Поэтому, если вы хотите изменить исходный указатель, вы должны передать указатель на указатель.

2 голосов
/ 07 января 2020

Я читал, что массивы передаются по ссылке на функции

Это не совсем верно. Когда вы передаете массив функции, указатель передается. Изменение указателя не изменит массив. Однако вы можете изменить массив с помощью указателя. Вот почему b[2]=1; работает. b по-прежнему просто указатель, который был передан как копия, поэтому b=b+2; не изменит массив.

Он не перемещает указатель на шаг вперед. Почему это так?

Он действительно перемещается на b вперед, но b является локальным для foo и впоследствии исчезает без изменения массива. Если вы сделали это, например.

void foo(int *b)
{
    b=b+2;
    b[2]=1;
}

Тогда это изменится validArray[4].

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