Почему мы должны использовать двойной указатель, когда передаем массив Dynami c в качестве параметра функции? - PullRequest
0 голосов
/ 04 апреля 2020

Я относительно новичок в программировании, и я пытаюсь понять некоторые концепции с помощью указателей. Я получил его по большей части, и я искал в динамическом распределении памяти c, и я понял, что мне нужно создать указатель, и функция mallo c вернет первый адрес выделенного пространства, которое мы поместили в указатель создан. Это имеет большой смысл, потому что это делает вектор dinami c таким же, как обычный вектор, верно? Поскольку вектор stati c также имеет имя вектора, указатель на первый элемент. Но почему, когда я пытаюсь, например, изменить размер вектора с помощью функции reallo c в функции, я понимаю, что мне нужно использовать двойной указатель в качестве параметра. Примерно так:

void function(int **vector){
    *vector=(*int)realloc(*vector, sizeof(int)*n);
}

Может кто-нибудь объяснить, спасибо!

Ответы [ 2 ]

0 голосов
/ 04 апреля 2020

Когда вызывается функция, объявленная как void function(int *vector), ей передается только значение int * - просто указатель на первый элемент вектора (массив). Если эта функция вызывается с function(MyVector), то внутри функции vector относится только к копии переданного значения. Это не относится к MyVector, и изменение vector не изменит MyVector.

Когда вызывается функция, объявленная как void function(int **vector), ей передается значение int ** - a указатель на указатель на первый элемент вектора. Если эта функция вызывается с function(&MyVector), то внутри функции vector ссылается на копию указателя на указатель. Однако, поскольку это указатель на указатель, то *vector ссылается на указатель на первый элемент массива. То есть *vector - это не просто копия указателя, это фактический указатель, MyVector в вызывающей стороне.

Итак, в первой функции vector = realloc(…); не изменяется MyVector в звонилке. Во второй функции *vector = realloc(…); меняет MyVector в вызывающем абоненте.

0 голосов
/ 04 апреля 2020

Если у вас есть функция, подобная этой

void f( T item );

, где T - некоторый спецификатор типа и вызывает его как

T object;
f( object );

, тогда функция получает копию своего аргумента. Это можно представить следующим образом

T object;
f( object );

//....

void f( /* T item */ )
{
    T item = object;
    // ...
}

Таким образом, изменения копии в функции не влияют на исходный объект, переданный функции в качестве аргумента.

Чтобы изменить исходный объект Вы должны передать его по ссылке. Например,

void f( T *item )
{
    *item = new_value;
    //...
}

//...

T object;
f( &object );

Если у вас есть объект типа int, который вы хотите изменить в функции, просто замените спецификатор типа T на тип int, и вы получите.

void f( int *item )
{
    *item = new_value;
    //...
}

//...

int object;
f( &object );

Если объект имеет тип int *, замените T на int *, и вы получите

void f( int **item )
{
    *item = new_value;
    //...
}

//...

int *object;
f( &object );

Вот демонстрационная программа.

#include <stdio.h>
#include <stdlib.h>

void f( int *x )
{
    *x = 20;
}

void g( int **p )
{
    *p = malloc( sizeof( int ) );
    **p = 30;
}

int main(void) 
{
    int x = 10;

    printf( "x = %d\n", x );

    f( &x );

    printf( "x = %d\n", x );

    int *px = &x;

    printf( "*px = %d\n", *px );

    g( &px );

    printf( "*px = %d\n", *px );

    free( px );

    return 0;
}

Его выход

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