因为函数参数是按值传递的,所以要想改变变量,必须传递地址。
二级指针实际上就是指针变量的地址,如果传递二级指针,函数声明必须写**。
(void**)&必须是本质上就是指针变量的地址才可以做这样的转换,并不是说把一个一级指针也可以转换,void**的本质是标识一个二级指针。
&data就是(默认数据类型 **)&data,(void **)&data和&data还是同一块内存,只不过数据类型发生变化了。
如果默认数据类型是int,&data就是(int **)&data
一级指针:
-
void
-
swap ( int *a, int *b ){
-
int temp = 0;
-
temp = *a;
-
*a = *b;
-
*b = temp;
-
}
-
-
int
-
main ( int argc, char **argv ){
-
int a,b;
-
a = 16;
-
b = 32;
-
swap(&a, &b);
-
return ( a - b );
-
}
二级指针:
-
void swap(int **a, int **b)
-
{
-
int t;
-
t =**a;
-
**a =**b;
-
**b=t;
-
}
-
int main()
-
{
-
int i = 3;
-
int j = 5;
-
int *p = &i;
-
int *q = &j;
-
swap(&p, &q);
-
}
高级一点使用void**只是为了通用,可以交换各种类型。
-
void swap(void **a, void **b)
-
{
-
void *t;
-
t =*a;
-
*a =*b;
-
*b=t;
-
}
-
int main()
-
{
-
int i = 3;
-
int j = 5;
-
int *p = &i;
-
int *q = &j;
-
char *s1= "abc";
-
char *s2= "def";
-
swap(( void**)&p, ( void**)&q);
-
swap(( void**)&s1, ( void**)&s2);
-
}
注意char*是字符串指针,需要改变其对应的变量必须用地址,s1就是"abc"的起始地址,是不能被改变,要想改变s1必须用他的地址也就是&s1,所以需要void**:
-
void swap(void *a, void *b)
-
{
-
void *t;
-
t =a;
-
a =b;
-
b=t;
-
}
-
int main()
-
{
-
char *s1= "abc";
-
char *s2= "def";
-
swap(( void*)s1, ( void*)s2);
-
}
(void**)& 本质
在看《算法精解 C语言描述》的双链表dlist.c的代码看到这样一段
算法精解:C语言描述\examples_unix\examples\chtbl\ex-1.c
-
int *data;
-
*data = 11;
-
if (dlist_remove(& list, element, ( void **)&data) != 0)
-
return 1;
算法精解:C语言描述\examples_unix\source\dlist.c
-
int dlist_remove(DList *list, DListElmt *element, void **data) {
-
-
/*****************************************************************************
-
* *
-
* Do not allow a NULL element or removal from an empty list. *
-
* *
-
*****************************************************************************/
-
-
if (element == NULL || dlist_size( list) == 0)
-
return -1;
-
-
/*****************************************************************************
-
* *
-
* Remove the element from the list. *
-
* *
-
*****************************************************************************/
-
-
*data = element->data;
-
-
if (element == list->head) {
-
-
/**************************************************************************
-
* *
-
* Handle removal from the head of the list. *
-
* *
-
**************************************************************************/
-
-
list->head = element->next;
-
-
if ( list->head == NULL)
-
list->tail = NULL;
-
else
-
element->next->prev = NULL;
-
-
}
-
-
else {
-
-
/**************************************************************************
-
* *
-
* Handle removal from other than the head of the list. *
-
* *
-
**************************************************************************/
-
-
element->prev->next = element->next;
-
-
if (element->next == NULL)
-
list->tail = element->prev;
-
else
-
element->next->prev = element->prev;
-
-
}
-
-
/*****************************************************************************
-
* *
-
* Free the storage allocated by the abstract data type. *
-
* *
-
*****************************************************************************/
-
-
free(element);
-
-
/*****************************************************************************
-
* *
-
* Adjust the size of the list to account for the removed element. *
-
* *
-
*****************************************************************************/
-
-
list->size--;
-
-
return 0;
-
-
}
其实很简单:
data是指针变量;
&data是data指针变量的地址所以传递他就是void**
看下面这幅调试图就明白了,起始&data就是(int **)&data,(void **)&data和&data还是同一块内存,只不过数据类型发生变化了。