int main(void)
{
dlist_t *list = create_dlist(); //存放整数的链表
int arr[10];
for (int j = 0; j < 10; j++)
{
arr[j] = j;
}
d_elem_t node[10];
int i = 0;
for (i = 0; i < 10; i++)
{
init_elem(&node[i], &arr[i]);
}
for (i = 0; i < 10; i++)
{
dlist_push_back(list, &node[i]);
}
int index = 0;
int *data;
data = (int *)dlist_get_by_index(list, index);
printf("list[%d] = %d\r\n", index, *data);
return 0;
}
之前写了个链表程序发现了一个关于void *
指针的问题,当下面这句代码
init_elem(&node[i], &arr[i]);
当是这样的时候:
init_elem(&node[i], i);
下面这段代码打印的代码就会出错
data = (int *)dlist_get_by_index(list, index);
printf("list[%d] = %d\r\n", index, *data);
而其中错误的点就在于*data
,他接收回来的是一个指向空类型的指针。
通过一番折腾后发现问题,写了下面一个小程序验证:
void *ptr;
void set_val(void *p)
{
ptr = p;
}
void *get_val()
{
return ptr;
}
int main(void)
{
int val = 30;
set_val(val);
int *tmp = (int *)get_val();
printf("%d", tmp);
return 0;
}
在关于指针的认知里,我们知道指针要解引用才能取出其所存的值。
然后发现了一个不一样的情况,如下面这句代码:
printf("%d", tmp);
打印出来的tmp
是30,而不是一个地址。
由此推测是因为set_val(val);
存进去的不是val的地址,而是常量30
,所以使用它的时候直接类似字符串使用地址就可以获取到值,而不要*tmp
解引用。
将上述代码中main函数改成下面:
int main()
{
int val = 30;
set_val(&val);
int *tmp = (int *)get_val();
printf("%d", *tmp);
return 0;
}
当void set_val(void *p)
函数改上面代码set_val(&val)
时,空类型指针p接收的是val变量的地址,需要解引用 printf("%d", *tmp);
才能输出val的值30
一直知道指针是C语言的精华,却没留意过这种问题。
总结
上述问题只要理解一句话就可以理解:指针变量也是变量
,void *的指针也不例外。
int a = 520;
void *b = a; //给指针b赋值为520
printf("%d\r\n", b); //打印结果 520
此时当使用*b去访问,就会访问非法地址而程序崩溃。
int a = 520;
void *b = &a; //给指针b赋值为a变量的地址
printf("%d\r\n", *(int *)b); //打印结果520
C路漫漫其修远兮,吾将上下而求索…