由一个链表引出的关于C语言指向空类型指针的问题

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路漫漫其修远兮,吾将上下而求索…

猜你喜欢

转载自blog.csdn.net/qq_36413982/article/details/108752920
今日推荐