c中这两种铸造形式(void **)& a和(void *)a的差异

时间:2013-12-03 17:02:12

标签: c casting

我观察到使用一些预定义的函数,我应该将数据转换为void*,然后将其传递给函数。这很容易理解。

我的问题是这两个演员之间的区别是什么:

  1. (void **)&a
  2. (void*)a
  3. 我应该使用哪一种,有什么区别?

2 个答案:

答案 0 :(得分:1)

你写道,“这很容易理解”。显然不是。首先,您没有投射数据,数据没有发生任何变化。其次,使用a vs &a传递给函数的内容完全不同。 void指针只是对某些数据的引用。底层数据类型未知(对编译器)。由于这个原因,您无法执行指针运算,例如。

假设你使用malloc()一块内存来存储一些数据,返回的指针是值0x2020并分配给x。现在假设x位于存储器位置0x1000处的堆栈区域。这意味着x是0x2020。 * x是您放入malloc'd区域的数据。现在重要的部分..& x是0x1000,这是x的内存地址,在我们假设的情况下,这是在堆栈上。以下示例演示了一点void *void **。这只是一个快速的样本,而不是除了演示概念之外做任何事情的正确方法。

#include <stdio.h>

struct t1 { int a; };
struct t2 { int b; };

int testvppa(void **pp){
    void *p = *pp;
    struct t1 * pt = (struct t1 *)p; // need to cast in order to de-reference
    return pt->a;
}
int testvppb(void **pp){
    void *p = *pp;
    struct t2 * pt = (struct t2 *)p; // need to cast in order to de-reference
    return pt->b;
}
int testvp(void *p, int which){
    if (which == 1)
    {
        return testvppa(&p);
    }
    else{
        return testvppb(&p);
    }
}

int main(){
    struct t1 stuffa = { 123 };
    struct t2 stuffb = { 456 };
    void * vp;

   printf("stuffa: {%d} @ %p\n", stuffa.a, &stuffa);
   printf("stuffb: {%d} @ %p\n", stuffb.b, &stuffb);

   vp = &stuffa;
   printf("vp: %p test: %d\n", vp, testvp(vp,1));

   vp = &stuffb;
   printf("vp: %p test: %d\n", vp, testvp(vp,2));
   return 0;
}

在我的机器上运行会产生以下结果:(注意指针的地址会改变,但值123和456将是相同的。)

stuffa: {123} @ 0x7fff28116db0
stuffb: {456} @ 0x7fff28116dc0
vp: 0x7fff28116db0 test: 123
vp: 0x7fff28116dc0 test: 456

我的答案很可能比启发更令人困惑。这就是为什么对你的问题的实际正确答案正是Oli Charlesworth在评论中所说的:“我建议先学习C,然后发表问题”

答案 1 :(得分:0)

第一个将地址传递给指向函数的指针(指针指针)。通过取消引用它,该函数应该能够返回指向您的指针作为输出参数。

第二个只能用作输入参数。

示例(在C代码中):

struct stuff { int t; };

void allocate_stuff(void **allocated) {
    struct stuff *opaque = malloc(sizeof(*opaque));
    *allocated = opaque; /* the dereferencing I mentioned - sets "output" value */
}

void deallocate_stuff(void *allocated) {
    free(allocated);
}

void * handle = NULL;
allocate_stuff(&handle); /* can return pointer due to */
deallocate_stuff(opaque);

编辑:要理解为什么第一个是“输出参数”,你可以查看正式/实际的参数定义。