Почему нам нужно определить указатель на указатель, чтобы изменить список?* Перечисляет ли указатель на указатель?
Помните, что C передает все аргументы функции по значению - формальный аргумент в определении функции - это другой объект в памяти, отличный от фактического аргумента в вызове функции.Например:
void swap( int a, int b )
{
int tmp = a;
a = b;
b = tmp;
}
void foo( void )
{
int x = 1;
int y = 2;
swap( x, y );
}
a
- это другой объект в памяти, чем x
, а b
- это другой объект в памяти, чем y
, поэтому поменяйте местами a
и b
не влияет на x
и y
.Чтобы поменять местами значения x
и y
, необходимо передать им указатели :
void swap( int *a, int *b )
{
int tmp = *a;
*a = *b;
*b = tmp;
}
void foo( void )
{
int x = 1;
int y = 2;
swap( &x, &y );
}
выражение *a
- этотакой же как x
, поэтому запись в *a
такая же, как запись в x
.То же самое для *b
и y
.
Таким образом, для записи функции в параметр необходимо передать указатель на этот параметр:
void foo ( T *arg )
{
*arg = new_value(); // writes a new value to the thing arg points to
}
void bar( void )
{
T var;
foo( &var ); // write a new value to var
}
Это верно для любой не массив типа T
.Давайте заменим T
типом указателя P *
:
void foo( P **arg )
{
*arg = new_value(); // write a new *pointer* value to the thing arg points to
}
void bar( void )
{
P *var;
foo( &var ); // write a new pointer value to var
}
Семантика точно такая же - все, что изменилось - это тип.
Если функция может изменитьсяобъект list *
(скажем, указывающий его на новый заголовок списка), затем вы должны передать указатель на этот list *
объект:
void add_node( struct list_t **list, struct list_t *node )
{
if ( !*list || (node->value < (*list)->value) ) // make node new head of list
*list = node;
else
// add node somewhere else in the list
}
int main( void )
{
struct list_t *list = NULL;
...
struct list_t *node = newNode( value );
add_node( &list, node );
...
}