简体   繁体   English

这两种转换格式(void **)&a和(void *)a在c中的区别

[英]difference of these two casting format (void **) &a and (void *)a in c

I have observed that using some of the predefined functions, I should cast my data to void* and then pass it to the function. 我观察到,使用一些预定义的函数,我应该将数据转换为void* ,然后将其传递给函数。 This is simple to understand. 这很容易理解。

My question is what is the difference between these two casts: 我的问题是这两个演员之间有什么区别:

  1. (void **)&a
  2. (void*)a

Which one of them should I use and what is the difference? 我应该使用其中之一,有什么区别?

You wrote, "this is simple to understand". 您写道:“这很容易理解”。 Clearly it is not. 显然不是。 Firstly, you are not casting the data, nothing is happening to the data. 首先,您没有强制转换数据,数据没有任何反应。 Secondly, what you pass to the function with a vs &a is totally different. 其次,你传递给函数什么a VS &a是完全不同的。 A void pointer is simply a reference to some data. 空指针只是对某些数据的引用。 The underlying data type is unknown (to the compiler). 基础数据类型是未知的(对于编译器而言)。 Due to this fact, you cannot perform pointer arithmetic for example. 由于这个事实,例如您不能执行指针算术。

Let's say you malloc() a chunk of memory to store some data and the pointer returned is the value 0x2020 and is assigned to x. 假设您malloc()一块内存来存储一些数据,并且返回的指针值为0x2020并分配给x。 Now let's say x is on a region of the stack at memory location 0x1000. 现在,假设x在堆栈的某个区域中,内存位置为0x1000。 This means x is 0x2020. 这意味着x为0x2020。 *x is the data you put inside that malloc'd region. * x是您放入该分配区域内的数据。 Now the important part.. &x is 0x1000 which is the memory address of x and in our hypothetical case, this is on the stack. 现在重要的部分。&x是0x1000,它是x的内存地址,在我们的假设情况下,它在堆栈上。 The following example demonstrates a bit of void * and void ** . 下面的示例演示了一些void *void ** It is just a quick sample and not the correct way to do anything except demonstrate the concept. 这只是一个简单的示例,而不是除演示概念之外的正确方法。

#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;
}

Running on my machine has the following results: (Note the address of the pointers will change but values 123, and 456 will be the same.) 在我的计算机上运行具有以下结果:(请注意,指针的地址将更改,但值123和456相同。)

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

There's a good chance my answer will be more confusing than enlightening. 我的答案很有可能比启发性更令人困惑。 This is why the actual correct answer to your question is exactly what Oli Charlesworth said in his comment: "I suggest first learning C, and then posting questions" 这就是为什么您的问题的真正正确答案就是奥利·查尔斯沃思(Oli Charlesworth)在其评论中所说的:“我建议先学习C,然后发布问题”。

The first one passes an address to your pointer (pointer to pointer) to the function. 第一个将地址传递给函数的指针(指向指针的指针)。 By de-referencing it, the function should be able to return a pointer to you, as an output parameter. 通过取消引用它,该函数应该能够将指向您的指针作为输出参数返回。

The second can only be used as an input parameter. 第二个只能用作输入参数。

example (in C code): 示例(在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);

Edit: to understand why the first is an "output parameter" you could look at formal/actual parameter definitions. 编辑:要了解为什么第一个是“输出参数”,您可以查看形式/实际参数定义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM